(submitFormでは、フォームを指定すべきなのがわかりづらい例になっていたので修正 2016/11/1)
Laravelアプリの開発時に、テストする時とそうでない時で、別のデータベースを使うようにする方法です。これをやっておけば、テスト時に好き勝手にデータベースをいじれるので便利です。
PHP 用のテストフレームワークである Codeception を導入すると、テスト時に使用する環境設定ファイルを指定できるので、そこでデータベースの情報を変更できます。 Codeception は Laravel を始めとする様々なフレームワークに対応していて導入しやすく、テスト用の機能も充実しているので導入して損はありません。
Laravel5.3でプロジェクトを作成して、 Codeception を組み込んで、データベースのテストを行うまでの簡単な流れです。
目次
Laravelプロジェクトと Codeception の設定
- ターミナルを起動して、プロジェクトを作成するフォルダーを開く
- 以下で、プロジェクトを作成。プロジェクト名は適宜変更のこと
laravel new lara53-codeception cd lara53-codeception
- 続けて、 Codeception を組み込む
composer require codeception/codeception --dev
Codeceptionのセットアップ
以下を実行することで、Codeception のセットアップができます。
composer exec codecept bootstrap
これにより、 tests ディレクトリーと設定ファイル[codeception.yml]が作成されます。加えて、Acceptanceテスト(実際のWebブラウザーを使ったテスト), Functionalテスト(実際のWebブラウザーは使わない機能テスト), Unitテスト(単体テスト) の3つのスイート(suites)用の設定ファイルも作成されます。
この時点で、以下でテストが動きます。
composer exec codecept run
まだテスト内容がないので、「No tests executed!」と表示されます。
データベースを準備
MySQLを起動していなかったら、新しいターミナルを開いて、以下で起動します。
sudo mysqld_safe
Laravelプロジェクトのフォルダーにいるターミナルで、以下でテスト用のデータベースを2つ作成します。
- 以下で、MySQLに接続
mysql -u root -p
- パスワードを入力
- 以下で、テスト用と、通常用のデータベースの2つを作成
create database lara53_codeception; create database lara53_codeception_test;
- それぞれのアクセス用のユーザーを作成
create user 'lara53_code'@'localhost' identified by 'YourPassword1', 'lara53_code_test'@'localhost' identified by 'YourPassword2';
- それぞれのデータベースにアクセス権を設定
GRANT ALL ON lara53_codeception.* TO 'lara53_code'@'localhost'; GRANT ALL ON lara53_codeception_test.* TO 'lara53_code_test'@'localhost';
設定を作成
テスト用の環境ファイルを用意するために、以下で .env を複製します。
cp .env .env.testing
.env.testing のデータベース設定をテスト専用のものにしておけば、テスト時はテスト専用に作ったデータベース上でテストができるので、テストと他の作業のデータを切り離すことができます。
- .gitignore を開いて、 .env.testing を追加する
- .env をエディターで開いて、通常の利用データベースへの接続を設定する。以下、このページの例に沿った内容。適宜、自分の環境の値に変更のこと
DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=lara53_codeception DB_USERNAME=lara53_code DB_PASSWORD=YourPassword1
- 上書き保存する
- .env.testing をエディターで開いて、通常の利用データベースへの接続を設定する。以下、このページの例に沿った内容。適宜、自分の環境の値に変更のこと
DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=lara53_codeception_test DB_USERNAME=lara53_code_test DB_PASSWORD=YourPassword2
- APP_ENV を testing にしておく
- 上書き保存
データベースを作成
簡単に動作を試すために、ログイン機能を実装して、それでテストをしてみましょう。以下で、ユーザー登録できるようにします。
php artisan make:auth
http://localhost:8000/ をリロードしたり、開くと、右上に LOGIN と REGISTER のリンクが表示されます。続いて、以下でデータベースを作成します。
php artisan migrate
以上でできるのは、 .env で定義されたデータベースに対してです。以下で、登録状況を表示してみましょう。
mysql -u root -p <rootのパスワードを入力> use lara53_codeception; show tables;
以上で、[migrations][password_resets][users]の3つのテーブルが作成されていることが確認できます。念のため、テスト用のデータベースにはまだテーブルが登録されていないことを確認しましょう。
use lara53_codeception_test; show tables;
こちらはまだ作成していないので、「Empty set」と表示されます。 exit で mysql から抜けます。
通常のユーザーを登録しておく
- http://localhost:8000 を開いたら、[REGISTER]を押す
- 項目を入力して、ユーザーを登録する。メールアドレスは仮のもので良い
テスト用の設定を作成
Codeception で Laravel5 のテストが動くように設定をします。Codeception には以下のようなテスト方法があります。
- Webブラウザーの動作を模して機能のテストを行う Functionalテスト
- Seleniumを使って実際にWebブラウザー上で機能のテストを行う Acceptance テスト
- PHPの関数ベースで単体テストを行う Unit テスト
- ステータスレスのWebAPIのテストを行う API テスト
- などなど
ここでは、 Functional テストで、テスト用のデータベースへのユーザー登録を試します。
Functionalテストの設定
Laravel5 - Codeception - Documentation を参考に設定を作成します。
- tests/functional.suite.yml をエディターで開く
- 以下のように設定する
class_name: FunctionalTester modules: enabled: - Laravel5: environment_file: .env.testing run_database_migrations: true - \Helper\Functional
- 上書き保存する
テストを作成する
04-FunctionalTests - Codeception - Documentation を参考にテストを作成します。
- ターミナルから、以下を実行
composer exec codecept g:cest functional User
- tests/functional/UserCest.php ができるので、エディターで開く(Cestとは、 Codeception のテスト用のファイルのこと)
- tryToTest()メソッドに、以下のコードを追加
public function tryToTest(FunctionalTester $I) { // ユーザー数が0であることを確認する \PHPUnit_Framework_Assert::assertEquals(0, App\User::all()->count()); // ユーザー登録ページを表示 $I->amOnPage('/register'); // 必要な情報を設定して、ユーザー登録フォームのsubmitを押す(2016/11/1に変更) $I->submitForm('#registerUserForm', [ 'name' => 'TestUser', 'email' => 'test@test.com', 'password' => 'testtest', 'password_confirmation' => 'testtest' ]); // ユーザーの登録に成功したら、以下のメッセージが表示される $I->see('You are logged in!'); // ユーザー数が増えて1になっていることを確認する \PHPUnit_Framework_Assert::assertEquals(1, App\User::all()->count()); }
submitFormで登録フォームを指定できるようにIDを追加します。
- resources/views/auth/register.blade.php をエディターで開く
- <form から始まる行を探して、以下のようにID属性を追加する
<form id="registerUserForm" class="form-horizontal" role="form" method="POST" action="{{ url('/register') }}">
以上で、テスト用のデータベースにユーザーを登録したことが確認できます。
通常のデータベースに変更がないことを確認する
通常のデータベースの中身を確認して、テストによる影響を受けていないことを確認します。ターミナルで以下を入力します。
mysql -u root -p <ルートパスワードを入力> use lara53_codeception; select * from users;
データに変更がないことが確認できるはずです。