前回、Drupal 向け Behat の拡張その1 複数ステップの実行とカスタムステップの作成(前編)という記事を書きました。その記事では、シナリオのステップを複数実行とパラメータを持たないカスタムステップの作成をしました。今回は、ステップにパラメータがあるカスタムステップの作成を行います。
パラメータがあるカスタムステップの作成
正規表現を使用しないステップ
作成するテストシナリオは下記になります。
Feature 名はパラメータがないカスタムステップと同じですが、シナリオ名は異なっています。Behat では 1つの Feature に複数のシナリオを含むことが出来るので、前回作成したシナリオの下に続けてシナリオを書くことが出来ます。上記のテストシナリオは下記のようになります。
Scenario: カスタムステップの作成2
# シナリオの中身
Given I am not logged in
When I go to random URL start with "hogehoge"
Then print current URL
未定義ステップのエラーメッセージに作成する関数のヒントは下記のようになります。
--- FeatureContext has missing steps. Define them with these snippets:
/**
* @When I go to random URL start with :arg1
*/
public function printCurrentDate() :void
{
echo (new DateTime())->format('Y/m/d H:i:s');
}
:arg1
という部分がステップで指定するパラメータとなります。:arg1
は定義済みのステップを表示する時にも出力されるので、後で分かりやすい名前に変更しておきます。
ページ遷移の実装は、パラメータがない時のカスタムステップで確認したファイルにある、When /^(?:|I )go to "(?P<page>[^"]+)"$/
のステップのソースコードを参考にします。
/**
* Opens specified page
* Example: Given I am on "http://batman.com"
* Example: And I am on "/articles/isBatmanBruceWayne"
* Example: When I go to "/articles/isBatmanBruceWayne"
*
* @Given /^(?:|I )am on "(?P<page>[^"]+)"$/
* @When /^(?:|I )go to "(?P<page>[^"]+)"$/
*/
public function visit($page)
{
$this->visitPath($page);
}
$this->visitPath($page);
で遷移できることが分かります。最終的にソースコードは以下のようになります。
/**
* @When I go to random URL start with :start
*/
public function iGoToRandomUrlStartWith(string $start) :void
{
$next_url = strlen($start) ? "{$start}/" : "";
$url_length = random_int(6, 10);
$create_random_url = function (int $length = 8) :string {
$random_url = "";
for($i = $length; $i; $i--) {
$seed = random_int(65, 90);
$is_capital = random_int(0, 1);
$random_url .= $is_capital ? chr($seed) : chr($seed + 32);
}
return $random_url;
};
$next_url .= $create_random_url($url_length);
$this->visitPath($next_url);
}
余談ですが、When /^(?:|I )go to "(?P<page>[^"]+)"$/
のステップの実装は、先述のソースコードを見ると分かるとおり Given
、When
の両方で使えるようになっています。このように、コメントのところで Given
、When
、Then
での記述の仕方をそれぞれ設定しておけば、それぞれのところでステップが使用可能になります。
正規表現を使用するステップ
先ほど作成した正規表現を使わないカスタムステップでは、必ず When I go to random URL start with :start
という形であるため、毎回主語の "I" を書かなければなりません。前回説明した When /^(?:|I )go to "(?P<page>[^"]+)"$/
のように主語の "I" がなくても動作するように正規表現を用いて柔軟なカスタムステップを作成します。
作成するテストシナリオは下記になります。
上記のテストシナリオは下記のようになります。
Scenario: カスタムステップの作成3
# シナリオの中身
Given I am not logged in
When I go to random 8 chars URL start with "foobar"
Then print current URL
Behat を実行すると、未定義のステップのヒントは下記のようになります。
--- FeatureContext has missing steps. Define them with these snippets:
/**
* @When I go to random :arg2 chars URL start with :arg1
*/
public function iGoToRandomCharsUrlStartWith($arg1, $arg2)
{
throw new PendingException();
}
このソースを /path/to/behat/behat-tests/features/bootstrap/FeatureContext.php
に追記しますが、このままだと正規表現を使用しないパターンと変わらないのでこれを変更していきます。
正規表現を使用するとなると下記の箇所が対象になるかと思います。
- 主語の "I"
- URL の長さを決める指定文字数の数字
- 指定文字数が 1 だった時の "chars" の単数形対応
- URL を始めるときに指定する文字列
これらに正規表現を当てはめると、
@When I go to random :arg2 chars URL start with :arg1
→
@When /^(|I )go to random \d+ chars? URL start with ".*"$/
と置き換えることが出来ます。しかし、この状態では Behat を実行した時に何も PHP の関数には値を渡されません。
Behat ではパラメータとして PHP の関数に渡したい場合、PHP の正規表現のサブパターンにある (?P<subpattern_name>regexp)
の形(名前付きサブパターン)にする必要があります。今回の場合、パラメータとして渡したいのは、URL の長さの文字数と URL の開始を指定する文字列であるため、これらを名前付きサブパターンに変更すると、
@When /^(|I )go to random \d+ chars? URL start with ".*"$/
→
@When /^(|I )go to random (?P<length>\d+) chars? URL start with "(?P<start>.*)"$
という形になります。最終的にソースコードは以下のようになります。
/**
* @When /^(?:|I )go to random (?P<length>\d+) chars? URL start with "(?P<start>.+)"$/
*/
public function iGoToRandomCharsUrlStartWith(string $start, int $length):void
{
$next_url = strlen($start) ? "{$start}/" : "";
$create_random_url = function (int $length = 8) :string {
$random_url = "";
for($i = $length; $i; $i--) {
$seed = random_int(65, 90);
$is_capital = random_int(0, 1);
$random_url .= $is_capital ? chr($seed) : chr($seed + 32);
}
return $random_url;
};
$next_url .= $create_random_url($length);
$this->visitPath($next_url);
}
この実装ならば、下記のようにステップを記述しても問題なく動作するはずです。
Scenario: カスタムステップの作成3-1
# シナリオの中身
Given I am not logged in
When I go to random 1 char URL start with "foobar"
Then print current URL
Scenario: カスタムステップの作成3-2
# シナリオの中身
Given I am not logged in
When go to random 10 chars URL start with ""
Then print current URL
最後に、パラメータを取るカスタムステップを作成する場合、 PHP の実装では注意点があります。Behat では正規表現の有無にかかわらず、PHP の関数では引数の数をチェックしています。そのため、PHP の関数で可変長引数を使って実装しても正しく動作しません。
まとめ
- パラメータを受け取るカスタムステップを作成しました
- PHP 側の関数では引数となるパラメータの数がステップのパラメータの数と同じにする必要があります
- 正規表現を使ったカスタムステップの場合、ユーザのステップの記述が柔軟になる
- 主語の有無や単語の単数形・複数形に対応しやすくなる
- ただし、正規表現を使う場合はパラメータの箇所は名前付きサブパターンにする必要があります
Behat on Drupal 8 の記事一覧
回 | タイトル |
---|---|
第1回 | Drupal 8 に Drupal 向け Behat のスタンドアロンでの導入とシンプルなテストシナリオ |
第2回 | Drupal 向け Behat の拡張その1 複数ステップの実行とカスタムステップの作成(前編) |
第3回 | Drupal 向け Behat の拡張その2 カスタムステップの作成(後編) |