Test Driven Development(テスト駆動開発) in Laravel

最初にテストコードを書き、テストコードに適用するように毎回phpunitを実行しながら実装していく手法

### first step to do
$ composer create-project –prefer-dist laravel/laravel library
$ cd library
$ php artisan –version
$ ls -al
$ git init
$ git status
$ git add .
$ git commit -m “initial commit”

.env

DB_CONNECTION=sqlite

$ touch database/database.sqlite

phpunit.xml

<php>
        <server name="APP_ENV" value="testing"/>
        <server name="BCRYPT_ROUNDS" value="4"/>
        <server name="CACHE_DRIVER" value="array"/>
        <server name="DB_CONNECTION" value="sqlite"/>
        <server name="DB_DATABASE" value=":memory:"/>
        <server name="MAIL_DRIVER" value="array"/>
        <server name="QUEUE_CONNECTION" value="sync"/>
        <server name="SESSION_DRIVER" value="array"/>
        <server name="DB_CONNECTION" value="sqlite"/>
        <server name="DB_DATABASE" value=":memory:"/>
    </php>

tests/Feature/ExampleTest.php
tests/Feature/BookReservationTest.php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class BookReservationTest extends TestCase
{
    /**
     * A basic test example.
     *
     * @return void
     */
    public function testBasicTest()
    {
        $response = $this->get('/');

        $response->assertStatus(200);
    }
}
class BookReservationTest extends TestCase
{
    public function testa_book_can_be_added_to_the_library(){
        
        $this->withoutExceptionHandling();

        $response = $this->post('/books', [
            'title' => 'Cool book Title',
            'author' => 'victor',
        ]);
        $response->assertOk();

        $this->assertCount(1, Book::all());

    }
}

$ phpunit –filter testa_book_can_be_added_to_the_library
PHPUnit 8.5.0 by Sebastian Bergmann and contributors.

F 1 / 1 (100%)

Time: 163 ms, Memory: 16.00 MB

There was 1 failure:

1) Tests\Feature\BookReservationTest::testa_book_can_be_added_to_the_library
Response status code [404] does not match expected 200 status code.
Failed asserting that false is true.

/home/vagrant/library/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestResponse.php:88
/home/vagrant/library/tests/Feature/BookReservationTest.php:15

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.

route

Route::post('/books', 'BooksController@store');

$ phpunit –filter testa_book_can_be_added_to_the_library
1) Tests\Feature\BookReservationTest::testa_book_can_be_added_to_the_library
Illuminate\Contracts\Container\BindingResolutionException: Target class [App\Http\Controllers\BooksController] does not exist.

$ php artisan make:controller BooksController

class BooksController extends Controller
{
    //
    public function store(){	
    }
}

$ phpunit –filter testa_book_can_be_added_to_the_library
1) Tests\Feature\BookReservationTest::testa_book_can_be_added_to_the_library
Error: Class ‘Tests\Feature\Book’ not found

$ php artisan make:model Book -m

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Book;

class BooksController extends Controller
{
    //
    public function store(){
    	Book::create([
    		'title' => request('title'),
    		'author' => request('author')
    	]);
    }
}

Book.php

class Book extends Model
{
    protected $quarded = [];
}

migration file

Schema::create('books', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('title');
            $table->string('author');
            $table->timestamps();
        });

>>> \Schema::getColumnListing(‘books’);
=> [
“id”,
“title”,
“author”,
“created_at”,
“updated_at”,
]

class BookReservationTest extends TestCase
{

    use RefreshDatabase;
    
    public function testa_book_can_be_added_to_the_library(){
        

        $this->withoutExceptionHandling();

        $response = $this->post('/books', [
            'title' => 'Cool book Title',
            'author' => 'victor',
        ]);
        $response->assertOk();

        $this->assertCount(1, Book::all());

    }
}

$ phpunit –filter testa_book_can_be_added_to_the_library
PHPUnit 8.5.0 by Sebastian Bergmann and contributors.

. 1 / 1 (100%)

Time: 223 ms, Memory: 20.00 MB

OK (1 test, 2 assertions)

テストコードを正確に書ければ、phpunitによるメッセージに沿って順番に進めることができる。
ただ、これ、migrationfile, route, model, controller書くだけになのに、時間かかりすぎるな。手が空いている時などはいいかもしれないが、毎回これやってたら開発効率が極端に落ちるように思うので、ケースバイケースだが、積極的には採用しずらい。