1. 序章

Cucumber フックは、すべてのシナリオまたはステップに対して特定のアクションを実行する場合に便利ですが、Gherkinコードでこれらのアクションを明示的に指定する必要はありません。

このチュートリアルでは、 @ Before @ BeforeStep、@ AfterStep、、および@Afterキュウリフックについて説明します。

2. キュウリのフックの概要

2.1. フックはいつ使用する必要がありますか?

フックを使用して、ビジネス機能の一部ではないバックグラウンドタスクを実行できます。 そのようなタスクは次のようになります。

  • ブラウザの起動
  • Cookieの設定またはクリア
  • データベースへの接続
  • システムの状態を確認する
  • モニタリング

監視のユースケースは、ダッシュボードをテストの進行状況でリアルタイムに更新することです。

フックはGherkinコードでは表示されません。 したがって、それらをキュウリの背景または特定のステップの代わりと見なすべきではありません。

テストの実行中にフックを使用してスクリーンショットを撮る例を見ていきます。

2.2. フックの範囲

フックはすべてのシナリオに影響します。したがって、専用の構成クラスですべてのフックを定義することをお勧めします。

すべてのグルーコードクラスで同じフックを定義する必要はありません。 グルーコードを使用して同じクラスでフックを定義すると、コードが読みにくくなります。

3. フック

まず、個々のフックを見てみましょう。 次に、フックを組み合わせたときにどのように実行されるかを確認する完全な例を見ていきます。

3.1. @Before

@Before で注釈が付けられたメソッドは、すべてのシナリオの前に実行されます。 この例では、すべてのシナリオの前にブラウザーを起動します。

@Before
public void initialization() {
    startBrowser();
}

複数のメソッドに@Beforeのアノテーションを付けると、ステップが実行される順序を明示的に定義できます。

@Before(order=2)
public void beforeScenario() {
    takeScreenshot();
}

2orderパラメーターの値としてアノテーションに渡すため、上記のメソッドは2番目に実行されます。 初期化メソッドのorderパラメーターの値として1を渡すこともできます。

@Before(order=1)
public void initialization()

したがって、シナリオを実行すると、 initialization()が最初に実行され、 beforeScenario()が2番目に実行されます。

3.2. @BeforeStep

@BeforeStep で注釈が付けられたメソッドは、すべてのステップの前に実行されます。 すべてのステップの前に、注釈を使用してスクリーンショットを撮りましょう。

@BeforeStep
public void beforeStep() {
    takeScreenshot();
}

3.3. @AfterStep

@AfterStep で注釈が付けられたメソッドは、すべてのステップの後に実行されます。

@AfterStep
public void afterStep() {
    takeScreenshot();
}

ここでは@AfterStepを使用して、すべてのステップの後にスクリーンショットを撮りました。 これは、ステップが正常に終了したか失敗したかに関係なく、発生します。

3.4. @After

@After で注釈が付けられたメソッドは、すべてのシナリオの後に実行されます。

@After
public void afterScenario() {
    takeScreenshot();
    closeBrowser();
}

この例では、最後のスクリーンショットを撮り、ブラウザを閉じます。 これは、シナリオが正常に終了したかどうかに関係なく発生します

3.5. シナリオパラメーター

フックアノテーションが付けられたメソッドは、シナリオタイプのパラメーターを受け入れることができます。

@After
public void beforeScenario(Scenario scenario) { 
    // some code
}

タイプScenarioのオブジェクトには、現在のシナリオに関する情報が含まれています。 シナリオ名、ステップ数、ステップ名、およびステータス(合格または不合格)が含まれます。 これは、合格したテストと不合格のテストに対して異なるアクションを実行する場合に役立ちます。

4. フックの実行

4.1. ハッピーフロー

4種類すべてのフックを使用してCucumberシナリオを実行するとどうなるかを見てみましょう。

Feature: Book Store With Hooks
  Background: The Book Store
    Given The following books are available in the store
      | The Devil in the White City          | Erik Larson |
      | The Lion, the Witch and the Wardrobe | C.S. Lewis  |
      | In the Garden of Beasts              | Erik Larson |

  Scenario: 1 - Find books by author
    When I ask for a book by the author Erik Larson
    Then The salesperson says that there are 2 books

  Scenario: 2 - Find books by author, but isn't there
    When I ask for a book by the author Marcel Proust
    Then The salesperson says that there are 0 books

IntelliJ IDEでのテスト実行の結果を見ると、実行順序がわかります。

まず、2つの@Beforeフックが実行されます。 次に、すべてのステップの前後に、@BeforeStepフックと@AfterStepフックがそれぞれ実行されます。 最後に、@Afterフックが実行されます。 すべてのフックは両方のシナリオで実行されます。

4.2. 不幸な流れ:ステップが失敗する

ステップが失敗した場合に何が起こるか見てみましょう。 下のスクリーンショットでわかるように、失敗したステップの@Beforeフックと@Afterフックの両方が実行されます。 以降の手順はスキップされ、最後に@Afterフックが実行されます。

@After の動作は、Javaのtry-catchの後のfinally-clauseに似ています。 ステップが失敗した場合、これを使用してクリーンアップタスクを実行できます。 この例では、シナリオが失敗した場合でもスクリーンショットを撮ります。

4.3. 不幸な流れ:フックが失敗する

フック自体が失敗したときに何が起こるかを見てみましょう。 以下の例では、最初の@BeforeStepが失敗します。

この場合、実際のステップは実行されませんが、@AfterStepフックは実行されます。 @After フックが最後に実行されるのに対し、後続のステップも実行されません。

5. タグ付きの条件付き実行

フックはグローバルに定義され、すべてのシナリオとステップに影響します。 ただし、Cucumberタグを使用すると、フックを実行するシナリオを正確に定義できます。

@Before(order=2, value="@Screenshots")
public void beforeScenario() {
    takeScreenshot();
}

このフックは、@Screenshotsでタグ付けされたシナリオに対してのみ実行されます。

@Screenshots
Scenario: 1 - Find books by author 
When I ask for a book by the author Erik Larson 
Then The salesperson says that there are 2 books

6. Java 8

Cucumber Java 8 Support を追加して、ラムダ式ですべてのフックを定義できます。

上記の例の初期化フックを思い出してください。

@Before(order=2)
public void initialization() {
    startBrowser();
}

ラムダ式で書き直すと、次のようになります。

public BookStoreWithHooksRunSteps() {
    Before(2, () -> startBrowser());
}

@ BeforeStep @ After、@AfterStepでも同じことが機能します。

7. 結論

この記事では、キュウリのフックを定義する方法について説明しました。

どのような場合にそれらを使用すべきか、いつ使用すべきでないかについて話し合いました。 次に、フックが実行される順序と、条件付き実行を実現する方法を確認しました。

最後に、Java8ラムダ表記を使用してフックを定義する方法を確認しました。

いつものように、この記事の完全なソースコードは、GitHubから入手できます。