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