php unit テストの勉強を久しぶりに。。
- 既存のユーザーを使って
- 掲示板の投稿ページからpost 送信をして
- 掲示板一覧ページに戻る
この一連の流れをテストしてみましょう!
バージョン:laravel6.8
参考にしたのはやんばるさんのブログ。いつもありがとうございます!
テスト用ファイルを作成
まずはコードを書くファイルを作成。
php artisan make:test PostTest
というコマンドでFeature配下にテスト用のファイルができます。
php artisan make:test PostTest --unit
これでUnit配下に作成されます。
詰まったとこ
use PHPUnit\Framework\TestCaseとは
最初あまり考えずにUnit配下にファイルを作成して書いていたのですが、最小構成のテストでもエラーになる。
しかも、書き方が悪いというよりも根本的に間違っているような。。なんで??としばらく詰まってしまったのですが、
ファイルでuseしている記述を変えたらうまくいきました。
use PHPUnit\Framework\TestCase; //これをやめて use Tests\TestCase; //こっちを使う
でも use PHPUnit\Framework\TestCase ってファイル作成時から書いてあったのに・・・なんであかんの??
と調べたところ、
- use PHPUnit\Framework\TestCase ・・・ご本家phpのクラス
- use Tests\TestCase ・・・Laravelの機能を絡めて使うことができる拡張クラス(??)
なんて書けばいいのか難しいですが、とにかくLaravelが用意している機能を絡めて使うには後者をuseしなければいけない、ということです。
最初からFeature配下にファイルを作っていれば use Tests\TestCase が記述されていたのに、私がUnitに作ったからこうなったというオチでした。
データベースを指定する
テストコードの中で既存ユーザーとしてログインさせたい・・のに「そんなユーザーいないよ!」というエラーが出ました。
DBを確認してもちゃんと存在するし、ユーザーを変えてみてもダメ。。
なんで〜と思ってぐぐったところ、テストの場合phpunit.xmlというファイル(Laravelルートにあります)を触る必要があるようです。
私の場合DBがmysqlではない別のDBを見る指定になっていたため起こったエラーでした。
テスト用コード
/** * A basic unit test example. * * @test */ public function 掲示板に投稿処理() { $this ->actingAs(User::find(1)) ->get('/posts'); $this->withoutExceptionHandling(); $response = $this->withoutMiddleware() ->post('/posts' ,[ 'title' => 'テストタイトル', 'content' => 'テスト投稿' ]); $response->assertRedirect('/posts'); }
ポイント
- @testと書けばメソッド名にtest…を付けなくても良い
- テスト名は日本語でもいい
- 仕様上掲示板に投稿できるのはログインユーザーのみだったので、テストの際もログインユーザーを作る必要がある
- factoryを使ってログインユーザーを作成してもいいが、今回はひとまず既存ユーザーで代用
- $this->withoutExceptionHandling(); を書いておくと、エラー時にlogファイルではなくターミナルに表示されるので手間が省ける
テスト実行
テストを実行する際は、
vendor/bin/phpunit
とターミナルに入力するとテストが動きます。
ファイルで指定して実行
全てのテストではなく、動かしたいテストファイルを指定するなら
vendor/bin/phpunit ./tests/Unit/ExampleTest.php
のように指定すると良い。
モデルを指定して実行
vendor/bin/phpunit --filter モデル名
とするとモデルで指定可能。
関数を指定して実行
テストの関数を指定して実行する場合
vendor/bin/phpunit --filter 関数名
これでOK!
実行すると

成功したらこんな風に表示されます。
テストの詳細も表示するオプション
vendor/bin/phpunit --filter 関数名 --testdox
最後に –testdox とつけると少し見やすくなります^^
おまけ:ダミーユーザーを作成して実行
今回は簡単にするために既存ユーザーを使ってログインしましたが、既存のデータをむやみに使うのもあれなので
実際にはfactoryを使ったりするようです。
database/factories/UserFactory.php にて
$factory->define(User::class, function (Faker $faker) { return [ 'name' => $faker->name, 'email' => $faker->unique()->safeEmail, 'email_verified_at' => now(), 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password 'remember_token' => Str::random(10), ]; } );
こんな風にダミーユーザーを作る用意をしておく。
そして先ほどのテストコードを一部だけ変更
public function 掲示板に投稿処理() { $user = factory(User::class)->create(); //ここでダミーユーザー作成 $this ->actingAs($user) //ダミーユーザーでログイン ->get('/posts'); $this->withoutExceptionHandling(); $response = $this->withoutMiddleware()->post('/posts' ,[ 'title' => 'テストタイトル', 'content' => 'テスト投稿' ]); $response->assertRedirect('/posts'); }
これで、既存ユーザーを使わずテストできました!
DBを汚さないために
上記テストを実行すると、DBに実際にデータが挿入されます。
テストの度にデータが増えるのを防ぐために、以下を追記します。
use Illuminate\Foundation\Testing\DatabaseTransactions;
こちらをテストファイルに追記して、テストクラス内で
use DatabaseTransactions;
のようにすると、DBのデータは増えずテストだけが実行されます!