Laravel 在 GitHub Actions 上用 MySQL 跑測試

LaravelCI

Laravel 預設測試用的資料庫是 SQLite,可是正常線上都是用 MySQL,在跑測試的時候常常會因為兩邊不一致。這時候會建議可以用 MySQL 來跑測試,讓測試和正式兩邊可以保持一致,才不會有測試明明過了,但線上卻出現不一樣行為的狀況,而且 MySQL 測試執行速度更快~ (參考 Using MySQL for Testing (on Laravel))

本地測試設定

本地可以先複製好測試用的 .env.testing

cp .env.example .env.testing

和設定測試用的 MySQL 帳密相關資料:

DB_DATABASE=avividai_saas_test
DB_USERNAME=root
DB_PASSWORD=password

接著把 .env.testing 加進 .gitignore 裡:

.env
.env.backup
.env.production
.env.testing

最後產生密鑰和執行測試:

php artisan key:generate --env=testing
./vendor/bin/pest

設定 GitHub Actions

GitHub Actions 跑測試的範例 yaml,複製以下內容到 .github/workflows/tests.yml

name: Tests

on:
  push:
    branches: [main]

jobs:
  tests:
    name: Tests

    runs-on: ubuntu-latest

    env:
      DB_DATABASE: laravel
      DB_USERNAME: root
      DB_PASSWORD: password

    services:
      mysql:
        image: mysql:5.7
        env:
          MYSQL_DATABASE: laravel
          MYSQL_ALLOW_EMPTY_PASSWORD: false
          MYSQL_ROOT_PASSWORD: password
        ports:
          - 3306/tcp
        options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: 8.3
          extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, mysql, mysqli, pdo_mysql, bcmath, intl, gd, exif, iconv, imagick, fileinfo
          coverage: none

      - name: Setup problem matchers
        run: |
          echo "::add-matcher::${{ runner.tool_cache }}/php.json"
          echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"

      - name: Install dependencies
        run: composer install --prefer-dist --no-interaction

      - name: Setup environment key
        run: |
          php -r "file_exists('.env.testing') || copy('.env.example', '.env.testing');"
          php artisan key:generate --env=testing

      - name: Run tests
        run: vendor/bin/pest
        env:
          DB_PORT: ${{ job.services.mysql.ports[3306] }}

參考資料