– 想定する条件において、親子の各テーブルを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を細かくやる人はこだわりがあり、レベルが高い印象があります。