🎃

Laravel テストコード導入から実行まで (インメモリSQLite)

2021/08/13に公開

概要

Laravelを使ったプロジェクトでテストコード導入を行ったので、共有と作業記録を兼ねて記事を書いています。

実行環境

  • Windows10
  • PHP 7.3.8
  • Laravel 5.8

作業記録

準備

  1. テストでインメモリDB(SQLite)を使う
    1. データベースの接続設定を config/database.php に追加
    config/database.php
    /* 中略 */
    'connections' => [
    /* 他の接続設定 */
        'sqlite_testing' => [
            'driver' => 'sqlite',
            'database' => ':memory:',
            'prefix' => '',
        ],
    ],
    /* 中略 */
    
    1. PHPUnitで使う接続設定を変更
    phpunit.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <phpunit>
    /* 中略 */
        <php>
            <env name="APP_ENV" value="testing"/>
            <env name="DB_CONNECTION" value="sqlite_testing"/>
            <env name="CACHE_DRIVER" value="array"/>
            <env name="SESSION_DRIVER" value="array"/>
            <env name="QUEUE_DRIVER" value="sync"/>
        </php>
    </phpunit>
    

テストコード

  1. Tests\TestCase を継承した テストコードを作成
    今回はRepositoryのテストコードを書いてみます。

    tests/Unit/Repositories/ExampleRepositoryTest.php
    <?php
    
    namespace Tests\Unit\Repositories;
    
    use App\Repositories\ExampleRepository;
    use App\Models\Example;
    use Tests\TestCase;
    
    class ExampleRepositoryTest extends TestCase
    {
        protected $repository;
    
        public function setUp(): void
        {
        // 各テストの前に実行される
            parent::setUp();
    
            $this->repository = app(ExampleRepository::class);
    
            // データベースマイグレーション&シーダー
            $this->artisan('migrate');
            factory(Example::class, 1)->create(['id' => 1, 'name' => 'test_name']);
        }
    
        public function tearDown(): void
        {
            parent::tearDown();
        }
    
        public function test__getById(){
            $actual = $this->repository->getById(1);
    
            $this->assertSame(1, $actual->id);
            $this->assertSame('test_name', $actual->name);
        }
    
        public function test__create(){
            $request = array("name" => "test_name2");
            $actual = $this->repository->create($request);
        
            // 成功するとTrueが返却される想定
            $this->assertTrue($actual);
        
            $actual = DB::table('examples')->find(2);
    
            $this->assertSame('test_name2', $actual->name);
        }
    
        public function test__delete(){
            $request = 1;
            $actual = $this->repository->delete($request);
        
            // 成功するとTrueが返却される想定
            $this->assertTrue($actual);
        
            $actual = DB::table('examples')->get();
    
            // id=1 が削除され、 exsamples にはデータが
            $this->assertEquals(0, $actual->count());
        }
    
        public function test__update(){
            $request = array("id" => 1, "name" => "update_name");
            $actual = $this->repository->update($request);
        
            // 成功するとTrueが返却される想定
            $this->assertTrue($actual);
        
            $actual = DB::table('examples')->find(1);
    
            // update_nameに変更されている想定
            $this->assertSame('update_name', $actual->name);
        }
    }
    

テストを実行

  • 普通に実行

    # すべて実行
    .\vendor\bin\phpunit
    
    # Unitのみ実行
    .\vendor\bin\phpunit --testsuite Unit
    
  • テストの実行をスクリプト化
    チームへの共有やCIも意識してcomposerのスクリプトとして登録します。

    • 設定

      composer.json
      {
          /* 中略 */
          "scripts": {
              /* 他のスクリプト設定 */
              "test": [
                  "phpunit"
              ],
              "test-unit": [
                  "phpunit --testsuite Unit"
              ],
              "test-feature": [
                  "phpunit --testsuite Feature"
              ]
          },
          /* 中略 */
      }
      
    • 設定

      # Unitのみ実行
      composer test-unit
      

Discussion