GitLab で Laravel の CI、ただしテストだけ

はじめに

gitlab-ci で自動テストを組む機会があったので、忘れないように残しておく

CI なんだけどデプロイは対応していない。テストだけ

環境

  • MacOS (13.1)
  • Docker Desktop (4.12.0)
  • Laravel9

前提

  • GitLab のアカウントはあらかじめ用意していること
  • 空のプロジェクトを作ってローカルにクローンしていること
  • GitLab CI を実施するには以下のいずれかを実施が必要になる

手順

Laravel9 のプロジェクトを作ってコミットする

sail で Laravel9 のプロジェクトを作成する

curl -s https://laravel.build/sample-app | bash

コンテナを起動する

cd sample-app
./vendor/bin/sail up -d

ブラウザで http://localhost を開いて Laravel の初期画面を確認する

確認したらコンテナは一旦止める

./vendor/bin/sail down

プロジェクトの中身を全部 GitLab のプロジェクトフォルダに移動して、コミットして、プッシュする

ブランチを作る

ここでブランチを作って、以降はそちらで作業する

ユニットテストを組む

自動テストを試すために、DB接続も行う簡単なテストを用意する

まず、database/seeders/DatabaseSeeder.php を開いてコメントアウトされているコードをアンコメントする

public function run()
{
    \App\Models\User::factory(10)->create();

    \App\Models\User::factory()->create([
        'name' => 'Test User',
        'email' => 'test@example.com',
    ]);
}

次に、DBからユーザデータを取得して内容をチェックする簡単なテストを tests/Feature/ExampleTest.php に追加する

use App\Models\User;
:
public function test_the_application_returns_a_successful_response()
    {
        $response = $this->get('/');

        $response->assertStatus(200);

        // DBからユーザデータを取得して、内容をチェックする
        $user = User::where('email', 'test@example.com')->first();
        $this->assertNotNull($user);
        $this->assertEquals($user->name, 'Test User');
    }

ローカルでテストを試す前に、テスト実施の都度にテストDBを作成するように DatabaseMigrations トレイトを、データ投入も行うように protected $seed = true; を tests/TestCase.php に追加する

<?php

namespace Tests;

use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;

abstract class TestCase extends BaseTestCase
{
    use CreatesApplication;
    use DatabaseMigrations;

    protected $seed = true;
}

最後にコンテナを起動してユニットテストを実施する

# コンテナ起動
./vendor/bin/sail up -d

# ユニットテスト実施
./vendor/bin/sail php artisan test

こんな結果になるはず

PASS  Tests\Unit\ExampleTest
✓ that true is true

PASS  Tests\Feature\ExampleTest
✓ the application returns a successful response

Tests:  2 passed
Time:   0.84s

試しに 'Test User' を書き換えてからテストすると失敗するので、テストが正常に動作していることもわかると思う

ここまでの内容をコミットしておく

.env.testing を作成する

テスト用の環境設定ファイル .env.testing を作る

まず、.env.example をコピーして .env.testing を作る

次に下記のコマンドで APP_KEY を生成する

php artisan key:generate --env=testing

あとは .env.testing を開いて、APP_ENV=testing とDBまわりの環境変数を設定する

:
APP_ENV=testing
:
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=testing
DB_USERNAME=sail
DB_PASSWORD=password
:

.gitlab-ci.yml を用意する

プロジェクトルートに .gitlab-ci.yml ファイルを作成する

.gitlab-ci.yml に CI の定義だの指示だのを書くわけで、何を書くのかは リファレンス を読んでね、と言われても最初はわからないので テンプレート がたくさん用意されている

Laravel も用意されているけれど上手く動かなかったので、PHP のやつをコピペして使う

https://gitlab.com/gitlab-org/gitlab-foss/-/blob/master/lib/gitlab/ci/templates/PHP.gitlab-ci.yml

いくつか修正する

まず、なぜが pdo_pgsql をインストールするようになっているのを pdo_mysql に変更する

それと、node.js が必要なので、これもインストールするスクリプトを追加する

before_script:
  :
  # Install PHP extensions
  - docker-php-ext-install mbstring pdo_mysql curl intl gd xml zip bz2 opcache
  :
  # Install node.js
  - curl -sL https://deb.nodesource.com/setup_18.x | bash -
  - apt-get install -yqq nodejs

次に、DBまわりの設定を修正や追加をする

variables:
  # Configure mysql environment variables (https://hub.docker.com/r/_/mysql/)
  MYSQL_ROOT_PASSWORD: password
  MYSQL_DATABASE: testing
  MYSQL_USER: sail
  MYSQL_PASSWORD: password

最後にテストスクリプトを書き換える

test:
  script:
    - npm install
    - npm run build
    - php artisan migrate --env=testing
    - php artisan db:seed --env=testing
    - php artisan test --configuration phpunit.xml --env=testing

CI を実施する

ここまでの変更をコミットして、さらにプッシュもする

GitLab のコンソールからマージリクエストを作成する

.gitlab-ci.yml が存在するとパイプラインが開始されて自動でユニットテストが始まる

左の青いグラフのボタンを押して

test を押すと、パイプラインのログを見れるので、テストが実施状況を確認できる

成功したら Job Succeed と出る

おわりに

ひとまずテストは動かせた。最初の取っ掛かりにはなるんじゃないかと思う

カバレッジチェックとかしていないので、そのうちやっておきたい