アプリのテストを行うことで、動作の確認を実施しています。
書籍情報を管理しているbookdataテーブルのテストが完了したので、所有書籍情報を管理しているpropertyテーブルのテストを今回は実装していきます。
今回の目的
propertyテーブルに関するテストを実装し、正常動作することを確認する
動作失敗パターンは別途作成とする。
なぜやるか
プログラムによる正常動作テストを行い、問題がないか確認するため
やりたいこと
所有書籍の新規登録・編集・検索・削除の一連の動作が実施できることを確認する
やったこと
テストするべき項目を検討する
テストの準備をする
テスト用propertyファクトリーを作成する
テストコードを書く
実施内容
propertyテーブルを利用した動作をテストする
テストの実施項目を検討する
エラーなく処理が完了することをテストしてきます。
テスト項目をあげてみました。
- propertyページにアクセスする
- 所有書籍情報を登録する
- 所有書籍の一覧表示
- 所有書籍の詳細表示
- 編集
- 編集後表示確認
- 検索
- 検索結果確認
- 削除
- 削除後消去確認
これらをテストできるようにしていきます。
データやアプリ構造がほぼ同じであるため、前回作成したbookdataテーブルとほとんど同じ内容ですね。
テスト環境の準備
propertyテスト用の準備を実施してきます。
まず、テスト記述用ファイルの生成。
$ php artisan make:test PropertyTest
property生成用のファクトリーファイルも準備しておきます。
$ php artisan make:factory PropertyFactory
factoryデータを作成する。
property用ファクトリーは前回までに使用する場面があり、既に作成しています。
# ~/database/factories/PropertyFactory.php
use App\Property;
use Faker\Generator as Faker;
$factory->define(Property::class, function (Faker $faker) {
return [
'user_id' => 1,
'bookdata_id' => 1,
'number' => 1,
'getdate' => $faker->date,
'freememo' => $faker->name,
];
});
テストコードを書く
それでは実際にコードを書いていきます。
indexにアクセスする
まずはindexビューにアクセスできることから確認です。
# ~/tests/Feature/PropertyTest.php
namespace Tests\Feature;
use Tests\TestCase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use App\User;
use Illuminate\Support\Facades\Auth;
class PropertyTest extends TestCase
{
use DatabaseMigrations;
/**
* A basic feature test example.
*
* @return void
*/
public function test_indexAccess_ok()
{
$user = factory(User::class)->create(); // ユーザーを作成
$this->actingAs($user); // ログイン済み
$this->assertTrue(Auth::check()); // Auth認証済であることを確認
$response = $this->get('/property'); // propertyへアクセス
$response->assertStatus(200); // 200ステータスであること
}
}
ログイン必須となるため、ログイン処理をしてからアクセスすることを確認です。
テストを実施します。
$ vendor/bin/phpunit tests/Feature/PropertyTest.php
テストコマンドに現在テストしているPropertyTestを指定することで、指定のファイルのみテストを行っています。毎回全ファイルを実施する必要性がない場合は便利です。
PHPUnit 7.5.7 by Sebastian Bergmann and contributors.
. 1 / 1 (100%)
Time: 927 ms, Memory: 20.00 MB
OK (1 test, 2 assertions)
問題なくテストが完了しました。
所有書籍情報の一連処理を実施する
次に、所有書籍の登録・編集・詳細確認・削除の一連の動作をテストするコードを書きました。
# ~/tests/Feature/PropertyTest.php
public function test_propertyControll_ok()
{
$user = factory(User::class)->create(); // ユーザーを作成
$this->actingAs($user); // ログイン済み
$this->assertTrue(Auth::check()); // Auth認証済であることを確認
//// 書籍情報登録
factory(Bookdata::class)->create(); // 書籍を作成
//// createページアクセス
$response = $this->get('/property/create'); // createへアクセス
$response->assertStatus(200); // 200ステータスであること
$response->assertViewIs('property.create'); // book.createビューであること
//// 所有書籍登録
$propertydata = [
'user_id' => 1,
'bookdata_id' => 1,
'number' => 1,
'getdate' => '2000-01-01',
'freememo' => 'testmemo',
];
$response = $this->from('property/create')->post('property', $propertydata);
// 所有書籍保存
$response->assertSessionHasNoErrors(); // エラーメッセージがないこと
$response->assertStatus(200); // 200ステータスであること
$savebook = Property::all()->first(); // 保存されたデータを取得
// 登録されていることの確認(indexページ)
$response = $this->get('property'); // bookへアクセス
$response->assertStatus(200); // 200ステータスであること
$response->assertViewIs('property.index'); // book.indexビューであること
$response->assertSeeText($savebook->bookdata->title); // 登録タイトルが表示されていること
// 詳細ページで表示されること
$response = $this->get('property/'.$savebook['id']); // 指定bookへアクセス
$response->assertStatus(200); // 200ステータスであること
$response->assertViewIs('property.show'); // property.showビューであること
foreach ($savebook as $value)
{
$response->assertSeeText($value);
}; // savebookデータが表示されていること
//// 編集
$edit_post = 'property/'.$savebook['id']; // 編集パス
$response = $this->get($edit_post.'/edit'); // 編集ページへアクセス
$response->assertStatus(200); // 200ステータスであること
$response->assertViewIs('property.edit'); // property.editビューであること
// 編集内容
$editpropertydata = [
'number' => 2,
'getdate' => '1900-01-01',
'freememo' => 'testmemotest',
'_method' => 'PUT',
];
$response = $this->from($edit_post.'/edit')->post($edit_post, $editpropertydata);
// 編集実施
$response->assertSessionHasNoErrors(); // エラーメッセージがないこと
$response->assertStatus(302); // リダイレクト
$response->assertRedirect('/property'); // トップページ表示
$editproperty = Property::all()->first(); // 編集されたデータを取得
// 編集されていることの確認(indexページ)
$response = $this->get('property'); // propertyへアクセス
$response->assertStatus(200); // 200ステータスであること
$response->assertViewIs('property.index'); // property.indexビューであること
$response->assertSeeText($editproperty->bookdata->title); // 編集タイトルが表示されていること
//// 削除
$response = $this->from('property/'.$savebook['id'])
->post('property/'.$savebook['id'], [
'_method' => 'DELETE',
]); // 削除実施
$response->assertSessionHasNoErrors(); // エラーメッセージがないこと
$response->assertStatus(302); // リダイレクト
$response->assertRedirect('/property'); // トップページ表示
// 削除されていることの確認(indexページ)
$response = $this->get('property'); // propertyへアクセス
$response->assertStatus(200); // 200ステータスであること
$response->assertViewIs('property.index'); // property.indexビューであること
$response->assertDontSeeText($editproperty->bookdata->title);
// 削除タイトルが表示されていないこと
}
こちらも、基本的にはbookdataをテストした際とほぼ同じ内容となりました。
異なる点としては、登録後にindexでタイトル名表示を確認する際に、Property登録データからbookdataをリレーションによる参照を行っているあたりでしょう。
データ新規登録についても、ファクトリーではなく、postによるデータ登録のテストであるため配列を用意して登録を行っています。
所有書籍検索の処理を実施する
最後に所有書籍の検索処理をテストします。
// 検索
public function test_findTitle_ok_yesMatchFindTitle()
{
//// ユーザー生成
$user = factory(User::class)->create(); // ユーザーを作成
$this->actingAs($user); // ログイン済み
$this->assertTrue(Auth::check()); // Auth認証済であることを確認
// faker 自動生成
$bookdata = factory(Bookdata::class)->create();
$propertydata = factory(Property::class)->create();
//// 検索
// 検索の実施(findページ)
$find_post = 'property/find'; // 検索パス
$response = $this->get($find_post); // 検索ページへアクセス
$response->assertStatus(200); // 200ステータスであること
$response->assertViewIs('property.find'); // property.findビューであること
$response = $this->from($find_post)
->post($find_post, ['find' => $propertydata->bookdata->title]); // 検索実施
$response->assertSessionHasNoErrors(); // エラーメッセージがないこと
$response->assertStatus(200); // 200ステータスであること
$response->assertSeeText($propertydata->bookdata->title);
// bookdataタイトルが表示されていること
}
public function test_findTitle_ok_noMatchFindTitle()
{
//// ユーザー生成
$user = factory(User::class)->create(); // ユーザーを作成
$this->actingAs($user); // ログイン済み
$this->assertTrue(Auth::check()); // Auth認証済であることを確認
// faker 自動生成
$bookdata = factory(Bookdata::class)->create([
'title' => 'a'
]); // タイトル名aで作成
$propertydata = factory(Property::class)->create();
//// 検索
// 検索の実施(findページ)
$find_post = 'property/find'; // 検索パス
$response = $this->get($find_post); // 検索ページへアクセス
$response->assertStatus(200); // 200ステータスであること
$response->assertViewIs('property.find'); // property.findビューであること
$response = $this->from($find_post)->post($find_post, ['find' => 'b']); // bで検索実施
$response->assertSessionHasNoErrors(); // エラーメッセージがないこと
$response->assertStatus(200); // 200 ステータスであること
$response->assertViewIs('property.find'); // property.findビューであること
$response->assertSeeText('書籍がみつかりませんでした。'); // タイトルなしメッセージが表示されていること
}
通常検索結果及び、検索結果として書籍がなかった場合をテストしています。
事前に書籍情報と所有書籍についてファクトリーによって生成した上で検索を実行して結果表示を確認しています。
以上で一端正常動作についてはテスト完了です。
といいたいところでしたが、ここでいろいろと考えさせられることになりました。
所有書籍情報を登録しているので、登録後のindex一覧表示には登録したユーザー本人の書籍情報のみが表示されている…ことをテストする必要が有ります。
このため、登録後の情報表示に関してテスト項目を追加で実施する必要が有ります。
次の記事はこちら
fippiy.hatenablog.jp