Laravel + Codeception2 でブラウザテストを自動化する
この記事はLaravel Advent Calendar 2014 22日目です。今日はCodeceptionを使ったLaravelアプリケーションのブラウザテストの自動化を紹介したいと思います。
はじめに
Webアプリケーションの開発現場でよくある光景として、ブラウザを使って人力でポチポチやって動作確認をしたりしますよね。ユニットテストを書いているといっても、Webサーバやデータベースまで含めた実際に動いているシステム全体の結合テストとして、リリース前にはブラウザでの動作確認はできればやっておきたいもの。ただ、一度や二度ならまだしもリリースの度に何度も何度も人力でテストするのは大変です(主に精神的に)。リリース頻度が日に数度といったレベルの場合は、そもそも人力テスト自体が不可能になるということも。もうこれは自動化するしかないですね。ということでCodeceptionです。
Codeceptionはユニットテスト、機能テスト、受け入れテストをサポートしたフルスタックのPHP用テスティングフレームワークです。いわゆるBDDフレームワークといわれるもので(厳密にいうとどうなのかはわかりませんが……)、自然言語(英語)に近い記法でテスト対象の振る舞いを記述しテストを行うことができます。
Codeceptionがサポートする3種類のテストのなかでブラウザによるテストに相当するのが受け入れテスト(Acceptance Test)です。受け入れテストとは、アプリケーションの利用者であるユーザの視点から、アプリケーションが期待したとおりに動作するか確認するテストのことです。サイトトップにアクセスして、ナビバーからログインページに飛んで、ユーザ名とパスワードを入力して、ログインボタンをクリックして、Welcome!と表示されたらOK……こういったユーザからみたアプリケーションの挙動を記述したシナリオを元に、Guzzle+Symfony BrowserKitによるスクレイパー(CodeceptionではPhpBrowserと呼ばれています)やPhantomJS、Selenium WebDriverで実際に動作中のアプリケーションにアクセスして挙動をテストすることができます。
この記事ではLaravel Tricksをサンプルとして、Codeceptionで受け入れテストを記述する方法を紹介します。受け入れテストの実行にはPhpBrowserを使用します。PhpBrowserはJavaScriptの実行はできませんが、Codeceptionに標準で入っているのでお手軽です。JavaScriptが必要な場合はPhantomJSやSelenium WebDriverを使用する必要がありますが、これらは別途インストールが必要です。詳しくはCodeceptionのマニュアルを参照してください。
Laravel Tricksのセットアップ
受け入れテストを行うにはWebサーバ、データベース含めてアプリケーションが動作している必要があります。下準備としてまずはLaravel Tricksをローカル環境で動くようにしておきます。
Laravel Tricksのセットアップ自体は本題ではないので、ここではわたしの開発マシンにあわせてあらかじめ設定を済ませておいたforkを利用します*1。Laravel Tricksのセットアップについて詳しくはLaravel Tricksのドキュメントを参照ください。
$ git clone https://github.com/atijust/laravel-tricks.git $ composer install $ php artisan migrate $ php artisan db:seed $ php artisan serve
PHPの組み込みサーバが起動し、http://localhost:8000/でLaravel Tricksにアクセスできるようになります。このローカルホストで動いているLaravel Tricksにたいして受け入れテストを実行します。
Codeceptionのインストール
composerでcodeception/codeceptionをインストールします。
$ composer require "codeception/codeception:2.*"
テストに必要な各種ファイルが格納されたtestsディレクトリと、グローバル設定ファイルであるcodeception.ymlを生成します。
$ php vendor/bin/codecept bootstrap Initializing Codeception in /Users/atijust/Develop/laravel-tricks File codeception.yml created <- global configuration tests/unit created <- unit tests tests/unit.suite.yml written <- unit tests suite configuration tests/functional created <- functional tests tests/functional.suite.yml written <- functional tests suite configuration tests/acceptance created <- acceptance tests tests/acceptance.suite.yml written <- acceptance tests suite configuration tests/_output was added to .gitignore tests/_bootstrap.php written <- global bootstrap file Building initial Tester classes Building Actor classes for suites: acceptance, functional, unit \AcceptanceTester includes modules: PhpBrowser, AcceptanceHelper AcceptanceTester.php generated successfully. 48 methods added \FunctionalTester includes modules: Filesystem, FunctionalHelper FunctionalTester.php generated successfully. 13 methods added \UnitTester includes modules: Asserts, UnitHelper UnitTester.php generated successfully. 17 methods added Bootstrap is done. Check out /Users/atijust/Develop/laravel-tricks/tests directory
以上でCodeceptionのインストールは完了です。
シナリオを作成
例としてログインのシナリオを作成してみましょう。
Laravel Tricksのログインの流れは次のようになります。
/login
にアクセス- ユーザ名とパスワードを入力
- LOGINボタンをクリック
- 投稿したトリックの一覧が表示されればログイン成功
これをシナリオに書き下してみます。
まずはシナリオを生成します。
$ php vendor/bin/codecept generate:cept acceptance Signin Test was created in SigninCept.php
tests/acceptance/SigninCept.phpにひな形が生成されているのでシナリオを記述します。
<?php $I = new AcceptanceTester($scenario); $I->wantTo('log in as regular user'); $I->amOnPage('/login'); $I->fillField('#username','msurguy'); $I->fillField('#password','password'); $I->click('#wrap > div.container > div > div > div > form > div:nth-child(5) > button'); $I->see('My tricks');
なにをやっているかはだいたいわかるのではないでしょうか。
テストシナリオは自然言語(英語)に近いかたちで記述することができます。とはいってもDSLというわけではなく普通のPHPコードです。あくまでもそれっぽく記述できるというだけです*2。
まず$I->amOnPage('/login');
でログインページにアクセスします。
次に$I->fillField('#username','msurguy');
でユーザ名、$I->fillField('#password','password');
でパスワードをフォーム入力します。ユーザ名とパスワードはシーダーでデフォルトで用意されているものです。入力するフィールドはCSSパスで指定していますが他にもさまざまな指定方法が利用できます。
そして$I->click('#wrap > div.container > div > div > div > form > div:nth-child(5) > button');
でLOGINボタンをクリック。ここでもCSSパスでLOGINボタンを指定しています。
ログインが成功したら投稿したトリックの一覧が表示されるのですが、その際に「My Tricks」という文字列が画面に出ているはずなので、それがあればログイン成功とみなします。
テストの実行
テストを実行してみましょう。
アプリケーションのURLをtests/acceptance.suite.yml
に設定します。
config: PhpBrowser: url: 'http://localhost:8000/'
テストを実行します。
$ php vendor/bin/codecept run acceptance --steps Codeception PHP Testing Framework v2.0.9 Powered by PHPUnit 4.4.0 by Sebastian Bergmann. Acceptance Tests (1) ----------------------------------------------------------------------------------------------- Trying to log in as regular user (SigninCept) Scenario: * I am on page "/login" * I fill field "#username","msurguy" * I fill field "#password","password" * I click "#wrap > div.container > div > div > div > form > div:nth-child(5) > button" * I see "My tricks" PASSED -------------------------------------------------------------------------------------------------------------------- Time: 715 ms, Memory: 13.25Mb OK (1 test, 1 assertion)
成功したようです。
このようにしてCodeceptionを使えばブラウザを使ったテストを自動化することができます。ここでは非常な簡単な例のみで、使用したCodeceptionの機能も基礎的なものだけでしたが、受け入れテストを記述するための豊富な機能がCodeceptionには用意されています。スクショ撮ったりとかもできます。
以上、Laravel Advent Calendar 2014 22日目でした。