環境
Laravel v9.5.1 (PHP v8.1.3)
前提条件
PostモデルにUserで検索するscopeByUser()
を定義している。
Unitテストでこのメソッドをテストしたい。
public function scopeByUser($query, User $user): Builder
{
return $query->where('user_id', $user->id);
}
Before
/**
* scopeByUser()のテスト
* UserでPostを検索することができる
*/
public function testScopeByUser()
{
$users = User::factory()->count(2)->create();
$posts = Post::factory()->for($users[0])->count(5)->create();
$otherPost = Post::factory()->for($users[1])->create();
$results = Post::byUser($users[0])->get();
$this->assertEquals($results->count(), $posts->count());
$this->assertNotContains($otherPost->id, $results->pluck('id')->toArray());
}
scopeByUser()
の結果と用意したテストデータのpostの数が一致してることをテストしたいので一見良さそうだが、下記の2点でテストとしてはちょっと微妙。
- もしテストデータを変えてしまったときでも
$posts->count()
で都合よく計算されてしまう可能性がある - (Laravelのメソッドなので大丈夫だとは思うが)
$posts->count()
が正しいかもテストしなくてはいけなくなる
$this->assertEquals($results->count(), $posts->count());
After
/**
* scopeByUser()のテスト
* UserでPostを検索することができる
* 4人中3人のユーザーの投稿を検索した場合には、3人のユーザーの投稿のみが取得できる
*/
public function testScopeByUserIds()
{
$users = User::factory()->count(2)->create();
$posts = Post::factory()->for($users[0])->count(5)->create();
$otherPost = Post::factory()->for($users[1])->create();
$results = Post::byUserIds($userIds)->get();
$this->assertEquals($results->count(), 5);
$this->assertNotContains($otherPost->id, $results->pluck('id')->toArray());
}
変更点
- コメントで前提条件と結果を書く
- 投稿数を実際の数字で明記
$this->assertEquals($results->count(), 5);
テストとしてより正確で、仕様書としてもわかりやすくなった!