behat 3.0とJenkins CIでBDDに挑戦(5)

[behat]:http://behat.org/
[behat3]:http://docs.behat.org/en/v3.0/
[zombie.js]:http://zombie.labnotes.org
[phantomjs]:http://phantomjs.org/
[Jenkins CI]:http://jenkins-ci.org/

関連記事:

 * [behat3とzombiejsでBDDに挑戦(1)]
 * [behat3とzombiejsでBDDに挑戦(2)]
 * [behat 3.0 とzombiejsでBDDに挑戦(3)]
 * [behat 3.0とphantomjsでBDDに挑戦(4)]
 * behat 3.0とJenkins CIでBDDに挑戦(5)
 * [behatとChrome HeadlessでBDDを実践(6)]
[behat3とzombiejsでBDDに挑戦(1)]:http://qiita.com/dozo/items/be0ff9e9443413a32d25
[behat3とzombiejsでBDDに挑戦(2)]:http://qiita.com/dozo/items/4cb29ee55c4bd8891786
[behat 3.0 とzombiejsでBDDに挑戦(3)]:http://qiita.com/dozo/items/ec0448ffcbb703df9e43
[behat 3.0とphantomjsでBDDに挑戦(4)]:http://qiita.com/dozo/items/5a5f81061a5aade383d6
[behat 3.0とJenkins CIでBDDに挑戦(5)]:http://qiita.com/dozo/items/4de280e580bdc48c9d93
[behatとChrome HeadlessでBDDを実践(6)]:https://qiita.com/dozo/items/f023c3a4ae9c35768a65

ここ数か月ほど進化が止まっていた[behat]だが、
漸く[Jenkins CI]への対応が可能になったようだ。

ヾ(・ω<)ﾉ"　三三三●　ⅱⅲ コロコロ♪

------------------- ↓ 余談はここから ↓-------------------
# [behat3]と[Jenkins Ci]

※[behat3]のバージョンは3.0.15で(2015/03/24現在)それ以降は動作が変わる可能性があります。

Continuous Integration（CI, 継続的インテグレーション？）という言葉はご存じだろうか。
テストを絶え間なくやる（継続）ことで品質を維持する手法ということになるだろうか。
すでに完成しているシステムがあったとして、
その内容を修正すると一つの問題は解決しても別の場所で問題が発生することがある。
それを防ぐためにテストを常にし続けて問題の発見につなげるということだ。
テストには内部テスト(PHPUnitみたいやなやつ)と外部テスト(behat)と両方該当する。

[behat]のように外部テストに最適なツールにはこのCIには最適だろうと思う。
CIで用いられる代表的なツールが[Jenkins CI]だ。
これと[behat]の組み合わせを考えていく。

[Jenkins CI]にはプラグインでJUnitフォーマットを読み込む仕組みが存在するので、
[behat]側でJUnit形式で出力すれば組み込みは可能なはずだ。
[behat]2には各種フォーマットで出力する機能が標準装備されている。
[Jenkins CI]に対応しようと思えばコマンドラインにパラメータを追加するだけでよかったのだが、
何故か[behat3]にはそのシステムが削除されている。

オワタ━＼(^o^)／━( ﾟ∀)━(　 ﾟ)━(ﾟ　 )━(∀ﾟ )━＼(^o^)／━!!

では対応は無理かと思ったが、
そこは捨てる神あれば拾う神あり。
対応している素敵な人がいた。
https://github.com/Behat/Behat/pull/676
待っている人がやはり多かったようでコメントはいいねの嵐だ。

2015/3/22時点でマージされていたので、
これを使えば[Jenkins CI]にも対応できそうだ。

------------------- ↑ 余談はここまで ↑-------------------

ヾ(・ω<)ﾉ"　三三三●　ⅱⅲ コロコロ♪

------------------- ↓ 本題はここから ↓-------------------

### [behat3]のインストール

毎度毎度、ゼロからインストールしていているのは、
検索からこの記事に直接来たときでも問題ないようにするためで、
必要なければ読み飛ばしてもらっていい。

##### composerのインストール

```shell-session
$ curl http://getcomposer.org/installer | php  # composerのダウンロード
$ php composer.phar init -n                    # composer.jsonの生成
$ php composer.phar config bin-dir "bin/"      # binディレクトリ指定
$ php composer.phar install                    # venderディレクトリ生成
$  php composer.phar require "behat/behat=*@dev" "behat/mink=*@dev" "behat/mink-extension=*@dev" "behat/mink-browserkit-driver=*@dev" "behat/mink-goutte-driver=*@dev" "behat/mink-selenium2-driver=*@dev" --prefer-dist # 各種インストール
```

##### インストール確認
```shell-session
$ ./bin/behat --version
behat version 3.0-dev
```

##### [behat3]の設定
behatのプロジェクトを初期化する。
featuresディレクトリが新規に作成され必要なファイルが生成される。

```shell-session
$ ./bin/behat --init
+d features - place your *.feature files here
+d features/bootstrap - place your context classes here
+f features/bootstrap/FeatureContext.php - place your definitions, transformations and hooks here
```

##### サンプル実行
mink-extension内にあるサンプルを実行する。
Wikipediaで検索する的な内容。

```shell-session
$ cp ./vendor/behat/mink-extension/features/search.feature ./features/
$ cp ./vendor/behat/mink-extension/behat.yml.dist ./behat.yml
$ ./bin/behat
Feature: Search
  In order to see a word definition
  As a website user
  I need to be able to search for a word

  Scenario: Searching for a page that does exist               # features\search.feature:6
    Given I am on "/wiki/Main_Page"                            # Behat\MinkExtension\Context\MinkContext::visit()
    When I fill in "search" with "Behavior Driven Development" # Behat\MinkExtension\Context\MinkContext::fillField()
    And I press "searchButton"                                 # Behat\MinkExtension\Context\MinkContext::pressButton()
    Then I should see "agile software development"             # Behat\MinkExtension\Context\MinkContext::assertPageContainsText()

  Scenario: Searching for a page that does NOT exist        # features\search.feature:12
    Given I am on "/wiki/Main_Page"                         # Behat\MinkExtension\Context\MinkContext::visit()
    When I fill in "search" with "Glory Driven Development" # Behat\MinkExtension\Context\MinkContext::fillField()
    And I press "searchButton"                              # Behat\MinkExtension\Context\MinkContext::pressButton()
    Then I should see "Search results"                      # Behat\MinkExtension\Context\MinkContext::assertPageContainsText()

2 scenarios (2 passed)
8 steps (8 passed)
0m1.98s (15.81Mb)
```

### [Jenkins CI]対応
[Jenkins CI]でも読み込めるようにJUnitフォーマットで出力する

```shell-session
$ ./bin/behat --format=junit --out=.
$ cat defautl.xml
<?xml version="1.0" encoding="UTF-8"?>
<testsuites name="default">
  <testsuite name="Search" tests="2" skipped="0" failures="0" errors="0">
    <testcase name="Searching for a page that does exist" status="passed"></testcase>
    <testcase name="Searching for a page that does NOT exist" status="passed"></testcase>
  </testsuite>
</testsuites>
```
outで指定したディレクトリにxmlファイルが出力される。

### [Jenkins CI]のプロジェクト登録

インストールが完了すれば出力ディレクトリにxmlファイルが作成されるので、
それを[Jenkins CI]に登録する

プロジェクト作成
![jenkins_phpcs01.PNG](https://qiita-image-store.s3.amazonaws.com/0/40697/64d14e0c-7abe-a56a-c291-9e1667ab71bd.png)

ビルド設定
![jenkins_phpcs02.PNG](https://qiita-image-store.s3.amazonaws.com/0/40697/d9b360cb-0f6b-ed74-afd4-0804d8233a7c.png)

------------------- ↑ 本題はここまで ↑-------------------

ヾ(・ω<)ﾉ"　三三三●　ⅱⅲ コロコロ♪

------------------- ↓ 補足はここから ↓-------------------
[Jenkins CI]は深掘りするときりがないので別の機会にやるとして、
現状[Jenkins CI]と[behat3]との組み合わせをどう運用しているかを箇条書きにしてみると

 * ページの死活確認
 * ログイン後ページの死活確認
 * ページのリンク切れ確認
 * SEOのテキスト確認
 * UserAgentの挙動確認
 * WebAPIの動作保証

もちろん本番環境にかけている。