前回、Drupal 8 に Drupal 向け Behat のスタンドアロンでの導入とシンプルなテストシナリオという記事を書きました。その記事では、最後に簡単なテストシナリオを作成しましたが常に1つのステップと事前に定義されたステップだけでシナリオを組み立てることはかなり困難です。今回は複数ステップの実行と上記の記事でエラーメッセージの際に少し触れたカスタムステップの作成について説明していきます。
複数ステップの実行
前回作成したテストシナリオでは、前提条件、行う動作、期待する結果で実行するステップが1つずつでした。しかし、冒頭でも記述しましたが実際にテストシナリオを作成する際にステップが1つで済むことは少ないです。
今回の説明で使用するフィーチャーファイルを作成します。作成するファイル名は test2.feature にします。
cd /path/to/behat/behat-tests # Behat 動作ディレクトリ
touch features/test2.feature
作成するテストシナリオは下記になります。
今回は、前提条件、行う動作、期待する結果のそれぞれでステップを2つずつ記述しています。これらのステップを定義済みのステップから探し出すと、下記のようになります。
# Feature 名
Feature: テストフィーチャー2
# Scenario 名
Scenario: 複数ステップの実行
# シナリオの中身
Given I am not logged in
Given I am at ""
When I go to "hogehoge"
When I move backward one page
Then print current URL
Then the response status code should not be 404
この内容で、Behat を実行すると下記のように問題なく実行できます。
Feature: テストフィーチャー2
Scenario: 複数ステップの実行 # features/test2.feature:4
Given I am not logged in # Drupal\DrupalExtension\Context\DrupalContext::assertAnonymousUser()
Given I am at "" # Drupal\DrupalExtension\Context\MinkContext::assertAtPath()
When I go to "hogehoge" # Drupal\DrupalExtension\Context\MinkContext::visit()
When I move backward one page # Drupal\DrupalExtension\Context\MinkContext::back()
Then print current URL # Drupal\DrupalExtension\Context\MinkContext::printCurrentUrl()
│ http://localhost:8888/
Then the response status code should not be 404 # Drupal\DrupalExtension\Context\MinkContext::assertResponseStatusIsNot
()
しかし、全てステップの前に Given
、When
、Then
が付いているためどこからどこが前提条件を指すのかが分かりづらいです。Behat では、Given
、When
、Then
が複数存在している時、それらの2つ目以降は And
や But
に置き換えることが出来ます。それらを置き換えると下記のようになります。
# Feature 名
Feature: テストフィーチャー2
# Scenario 名
Scenario: 複数ステップの実行
# シナリオの中身
Given I am not logged in
And I am at ""
When I go to "hogehoge"
And I move backward one page
Then print current URL
But the response status code should not be 404
置き換えた後に Behat を実行すると、置き換える前と同様な結果が出力されます。
Feature: テストフィーチャー2
Scenario: 複数ステップの実行 # features/test2.feature:4
Given I am not logged in # Drupal\DrupalExtension\Context\DrupalContext::assertAnonymousUser()
And I am at "" # Drupal\DrupalExtension\Context\MinkContext::assertAtPath()
When I go to "hogehoge" # Drupal\DrupalExtension\Context\MinkContext::visit()
And I move backward one page # Drupal\DrupalExtension\Context\MinkContext::back()
Then print current URL # Drupal\DrupalExtension\Context\MinkContext::printCurrentUrl()
│ http://localhost:8888/
But the response status code should not be 404 # Drupal\DrupalExtension\Context\MinkContext::assertResponseStatusIsNot(
)
置き換えたことで、シナリオ内で Given
、When
、Then
がそれぞれ1回のみ出てくるようになったため、どこからどこが前提条件なのかが分かりやすくなりました。
Behat の公式ドキュメントのように And
や But
の部分でインデントをつけることで読みやすさを改善することが出来ます。
パラメータがないカスタムステップの作成
カスタムステップを作成するためのテストシナリオを用意します。
今回のテストシナリオでは、test3.feature というファイル名にします。
cd /path/to/behat/behat-tests # Behat 動作ディレクトリ
touch features/test3.feature
作成するテストシナリオは下記になります。
前提条件と行う動作に関しては、前回作成したテストシナリオとほとんど変わらないため定義済みのステップが存在します。しかし、“ステップの実行時間を表示する”は定義されていないため新たに定義を作成する必要があります。期待する結果への定義なので、最初の部分は Then
になります。動作は現在時刻を表示するので、
Then print current date
と記述できます。
上記のテストシナリオは下記のようになります。
# Feature 名
Feature: テストフィーチャー3
# Scenario 名
Scenario: カスタムステップの作成
# シナリオの中身
Given I am not logged in
When I go to "<front>"
Then print current date
もちろん、このシナリオを実行しても定義されていないため下記のようにエラーが出てきます。
--- FeatureContext has missing steps. Define them with these snippets:
/**
* @Then print current date
*/
public function printCurrentDate()
{
throw new PendingException();
}
エラーメッセージに作成する関数のヒントが書かれているため、これを /path/to/behat/behat-tests/features/bootstrap/FeatureContext.php
に追記します。追記する際は、コメントに見える
/**
* @Then print current date
*/
の部分も含めて追記します。(この部分がないとステップが未定義のままとして扱われます)
追記内容のままだと、throw new PendingException();
で例外を投げてしまい何もできないのでコードを書き換えていきます。
コードを書き換える前にすでに定義されている、ステップ実行時の URL を表示するステップ Then print current URL
のソースコードを見てみます。(Composer でインストールされたファイルならパスは、/path/to/behat/vendor/behat/mink-extension/src/Behat/MinkExtension/Context/MinkContext.php
です)
/**
* Prints current URL to console.
* Example: Then print current URL
* Example: And print current URL
*
* @Then /^print current URL$/
*/
public function printCurrentUrl()
{
echo $this->getSession()->getCurrentUrl();
}
該当部分を抜粋すると上記になります。Behat のシナリオでも echo
を使えば通常の PHP プログラムと同じく結果を出力できることが分かります。
echo
を使えばよいことが分かったので、コードを書き換えます。
/**
* @Then print current date
*/
public function printCurrentDate()
{
echo (new DateTime())->format('Y/m/d H:i:s');
}
書き換えた結果は上記のようになり、このテストシナリオを実行すると下記のようになります。
Feature: テストフィーチャー3
Scenario: カスタムステップの作成 # features/test3.feature:5
Given I am not logged in # Drupal\DrupalExtension\Context\DrupalContext::assertAnonymousUser()
When I go to "<front>" # Drupal\DrupalExtension\Context\MinkContext::visit()
Then print current date # FeatureContext::printCurrentDate()
│ 2016/12/08 12:35:02
2 scenarios (2 passed)
6 steps (6 passed)
0m0.52s (11.18Mb)
Then print current date
の次の行にステップの実行した時刻が表示されました。これで、引数がない時のカスタムステップが作成できました。
まとめ
今回の記事をまとめると以下のようになります。
- シナリオ内のステップで
Given
、When
、Then
が複数回使えることを示しました -
Given
、When
、Then
を複数回使用する場合はAnd
やBut
でも記述ができる-
And
やBut
で置き換えた方が、前提条件や行う動作、期待する結果の範囲が分かりやすくなる
-
- パラメータがないカスタムステップを作成した
- PHP での実装の際にステップの記述が必要になる
- パラメータが有るパターンは次回になります
Behat on Drupal 8 の記事一覧
回 | タイトル |
---|---|
第1回 | Drupal 8 に Drupal 向け Behat のスタンドアロンでの導入とシンプルなテストシナリオ |
第2回 | Drupal 向け Behat の拡張その1 複数ステップの実行とカスタムステップの作成(前編) |
第3回 | Drupal 向け Behat の拡張その2 カスタムステップの作成(後編) |