– 想定する条件において、親子の各テーブルをassertCount, assertEquals、assertNotNullでcheckする
– feature testとunit testの違い
-> userの挙動のテストがfeature test, unit testはuser操作が関係ない
– unit testのデータ生成にはfactoryを活用
$ php artisan make:test BookReservationsTest
namespace Tests\Unit;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
use App\Book;
use App\User;
class BookReservationsTest extends TestCase
{
use RefreshDatabase;
public function test_a_book_can_be_checked_out(){
$book = factory(Book::class)->create();
$user = factory(User::class)->create();
$book->checkout($user);
$this->assertCount(1, Reservation::all());
$this->assertEquals($user->id, Reservation::first()->user_id);
$this->assertEquals($book->id, Reservation::first()->book_id);
$this->assertEquals(now(), Reservation::first()->checked_out_at);
}
}
$ phpunit –filter test_a_book_can_be_checked_out
Tests\Unit\BookReservationsTest::test_a_book_can_be_checked_out
$ php artisan make:factory BookFactory -m Book
BookFactory.php
use App\Book;
use App\Author;
use Faker\Generator as Faker;
$factory->define(Book::class, function (Faker $faker) {
return [
'title' => $faker->sentence,
'author_id' => factory(Author::class),
];
});
$ phpunit –filter test_a_book_can_be_checked_out
$ php artisan make:factory AuthorFactory -m Author
use App\Author;
use Faker\Generator as Faker;
$factory->define(Author::class, function (Faker $faker) {
return [
'name' => $faker->name,
'dob' => now()->subYears(10),
];
});
Book.php
public function checkout(){
}
$ php artisan make:model Reservation -m
Book.php
public function checkout(User $user){
$this->reservations()->create([
'user_id' => $user->id,
'checked_out_at' => now(),
]);
}
public function reservations(){
return $this->hasMany(Reservation::class);
}
Reservation.php
protected $fillable = [
'user_id',
'book_id',
'checked_out_at'
];
migration file
Schema::create('reservations', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id');
$table->unsignedBigInteger('book_id');
$table->timestamp('checked_out_at');
$table->timestamp('checked_in_at');
$table->timestamps();
});
$ phpunit –filter test_a_book_can_be_checked_out
public function test_a_book_can_be_returned(){
$book = factory(Book::class)->create();
$user = factory(User::class)->create();
$book->checkin();
$this->assertCount(1, Reservation::all());
$this->assertEquals($user->id, Reservation::first()->user_id);
$this->assertEquals($book->id, Reservation::first()->book_id);
$this->assertEquals(now(), Reservation::first()->checked_in_at);
}
Book.php
public function checkin($user){
$reservation = $this->reservations()->where('user_id', $user->id)->whereNotNull('checked_out_at')->whereNull('checked_in_at')->first();
$reservation->update([
'checked_in_at' => now(),
]);
}
public function test_a_book_can_be_returned(){
$book = factory(Book::class)->create();
$user = factory(User::class)->create();
$book->checkout($user);
$book->checkin($user);
$this->assertCount(1, Reservation::all());
$this->assertEquals($user->id, Reservation::first()->user_id);
$this->assertEquals($book->id, Reservation::first()->book_id);
$this->assertEquals(now(), Reservation::first()->checked_in_at);
}
public function test_a_user_can_checkout_a_book_twice(){
$book = factory(Book::class)->create();
$user = factory(User::class)->create();
$book->checkout($user);
$book->checkin($user);
$book->checkout($user);
$this->assertCount(2, Reservation::all());
$this->assertEquals($user->id, Reservation::find(2)->user_id);
$this->assertEquals($book->id, Reservation::find(2)->book_id);
$this->assertNull(Reservation::find(2)->checked_in_at);
$this->assertEquals(now(), Reservation::find(2)->checked_out_at);
$book->checkin($user);
$this->assertCount(2, Reservation::all());
$this->assertEquals($user->id, Reservation::find(2)->user_id);
$this->assertEquals($book->id, Reservation::find(2)->book_id);
$this->assertNotNull(Reservation::find(2)->checked_in_at);
$this->assertEquals(now(), Reservation::find(2)->checked_in_at);
}
UnitTestを細かくやる人はこだわりがあり、レベルが高い印象があります。