🧪

【Laravel】自動テスト実行のためのPHPUnit環境構築

に公開

はじめに

LaravelでWebアプリケーションを開発し、デプロイが目前に迫ると「本当にすべて正常に動作するのか」と不安になる瞬間が訪れます。本番デプロイ前は、ローカルと挙動が異なることもあるため、事前の検証は不可欠ですが、自動テストを実施する前には様々な準備が必要です。本記事では、自動テスト実行のためのPHPUnit環境構築準備に必要な項目を紹介します。

対象者

  • Laravelアプリを初めて本番公開するエンジニア
  • アプリの手動テストに不安がある方
  • デプロイのたびに同じ手動テストの繰り返しから解放されたい方

テスト環境の準備手順

自動テストの目的は、本番環境にデプロイする前に、主要機能が意図通り動作するかどうかを網羅的に確認することです。
手動テストで確認しきれない部分を自動化することで品質を高めるため、以下の内容を実施することでテスト環境の構築準備ができます。

ファイル構成例

 tests/
├── Feature/
│   ├── Auth/
│   │   ├── LoginTest.php
│   │   └── RegisterTest.php
│   ├── User/
│   │   ├── AppFormTest.php
│   │   └── HealthFormTest.php
│   ├── Admin/
│   │   └── AdminUserManagementTest.php
│   └── Mail/
│       └── RegistrationMailTest.php
├── Unit/
│   └── Requests/
│       ├── RegisterRequestTest.php
│       ├── AppFormRequestTest.php
│       └── HealthFormRequestTest.php

事前準備チェックリスト(テスト実行前)

項目 コマンド・内容 備考
.env.testing の確認・作成 .env をベースに .env.testing を作成し、以下を上書き
APP_ENV=testing
APP_KEY=base64:xxx(正しいキー)
DB_DATABASE=:memory: または test_db
.env.testing が無いと暗号化エラー(cipher)が起こる
キャッシュのクリア php artisan config:clear
php artisan cache:clear
php artisan view:clear
.env.testing を反映するため
APP_KEY の生成(必要時) php artisan key:generate --env=testing .env.testing にキーがないと encryption エラー
テスト用マイグレーション php artisan migrate --env=testing または
php artisan migrate:fresh --env=testing
SQLite(:memory:)を使う場合は RefreshDatabase が自動実行
テスト用Seederの整備 DatabaseSeeder で必要な初期データや Enum 定義を整備
例:UserSeeder など
特定の状態が必要なテスト時
Factoryの定義確認 database/factories/*.php にテーブル定義と整合するフィールドを記述 FormData::factory() エラー回避に重要
テストデータベース接続確認 .env.testing でDB接続先を test 用(例:SQLite)にしているか DB_CONNECTION=sqliteDB_DATABASE=:memory: など

よくあるエラーと対処

エラー内容 対処
Unsupported cipher or incorrect key length .env.testingAPP_KEY が未設定 or 無効。php artisan key:generate --env=testing
Call to undefined method Model::factory() Factory ファイルが未作成 or namespace/return 書き忘れ
DBが空でテスト失敗 テスト用DBが初期化されていない。php artisan migrate:fresh --env=testing

テスト実行コマンド例

実行フロー

cp .env .env.testing  # 初回のみ
php artisan config:clear
php artisan key:generate --env=testing
php artisan migrate --env=testing
php artisan test # テスト実行
php artisan test --filter=User/
php artisan test --filter=Admin/
php artisan test --parallel

注意点

  • 本番サーバーでは APP_ENV=production に設定しておき、php artisan test が実行されないよう制限しておく
if (app()->environment('production')) {
    abort(403, '本番環境ではテストを実行できません');
}
  • テストの実行は、必ずローカルまたは検証環境で行うこと
  • Laravelのphpunit.xml内で、MailやDatabaseの設定がテスト用に切り替わっているか確認する

テスト実行環境における SQLite と MySQL の使い分けについて

テスト実行時に使用するデータベースとして、SQLite(特にin-memory)を使うことで、MySQLよりも構築が容易でスピードも速く、手軽にテストを繰り返すことができます。

比較項目 SQLite MySQL
セットアップ .env.testing に1行書くだけ MySQLサーバー起動・DB作成が必要
実行速度 非常に高速(in-memory対応) 中〜高速(DBサーバー次第)
CI/CD対応 GitHub Actionsなどで扱いやすい MySQLセットアップのコストがある
テストデータの巻き戻し RefreshDatabaseで初期化可 トランザクションやtruncateで対応
制約の厳密性 外部キー制約などが甘い 本番と同等の制約でテストできる

結論:どう使い分けるべき?

テスト目的 推奨DB 理由
バリデーション検証 SQLite 軽量・速い・構築が楽
CRUD確認 SQLite RefreshDatabase により毎回初期化が簡単
複雑なリレーション確認 MySQL 実際のDB構造と制約に近づけたい場合はMySQLが安全
本番に極めて近いテスト MySQL 全く同じ挙動を担保したい場合

まずはSQLiteで開発スピードを上げ、重要なロジックや制約まわりだけMySQLでのテストも併用するハイブリッドな戦略が現実的です。

テスト要件の整理

Webアプリのどんなテストをしたいか要件を整理しておくことも大切です。具体例を以下に記載します。

対象画面

  • 一般ユーザー画面(User)
  • 管理者画面(Admin)

テスト種別

  • 正常系(Happy Path)
  • 異常系(Validation error、認可エラーなど)

テスト範囲(例)

  • ログイン/登録/パスワードリセット
  • ユーザー情報登録・更新(user_data, form_data など)
  • 管理者画面でのユーザー一覧・編集
  • フォーム送信(AppForm・HealthForm)
  • メール送信(登録完了、管理者通知)

テスト内容の網羅基準

区分 チェックポイント例
認証関連 ログイン成功/失敗、リダイレクト確認
ユーザー登録 バリデーション、重複チェック、登録完了メール送信
各フォーム 入力正常系/未入力/形式不正/保存成功確認
画面遷移 ロールごとのルート制御、未ログイン時の挙動
Admin操作 管理者専用ページへのアクセス、編集処理の確認
メール送信 登録完了・通知メールが Mail::fake で送信されたか確認
CSRF/Session トークン未送信時の挙動、セッション期限切れ

チェック基準(例)

  • 全ルートURLについて1件以上の正常系・異常系テストを実装する
  • FeatureTestのカバレッジをroutes/web.php全体の80%以上とする
  • FormRequest単体でバリデーション条件の100%をUnitTest化する

実装方針

テスト要件が整理出来たら、実際にどんなテストコードを書いていくか実装方針を具体化します。

  • LaravelのFeatureTestを用いて、画面操作・レスポンスを検証
  • FormRequestのUnitTestでバリデーション単体確認
  • Mail::fake()でメール送信の挙動確認
  • DatabaseTransactionsを活用し、テスト後にデータをロールバック
  • データ準備はSeeder・Factoryを活用して再利用可能に

Mail::fake() の使用例

public function test_registration_mail_is_sent()
{
    Mail::fake();

    $response = $this->post('/register', [
        'name' => 'テストユーザー',
        'email' => 'test@example.com',
        'password' => 'password',
        'password_confirmation' => 'password',
    ]);

    Mail::assertSent(WelcomeMail::class, function ($mail) {
        return $mail->hasTo('test@example.com');
    });
}

DatabaseTransactions の使用例

use Illuminate\Foundation\Testing\DatabaseTransactions;

class RegisterTest extends TestCase
{
    use DatabaseTransactions;
    ...
}

CSRFトークン未送信時の異常系テスト例

public function test_form_submission_without_csrf_should_fail()
{
    $response = $this->post('/submit', [
        'name' => '未認証',
    ], ['X-CSRF-TOKEN' => '']);

    $response->assertStatus(419); // LaravelのCSRF保護エラー
}

おわりに

私はLaravelアプリをサーバーに本番公開する際、本当に全て動作するのか不安でテストを繰り返した経験があります。そんなとき、自動テストを実施しましたが、その環境を整えることにもいくつかの手順を踏まないといけませんでした。テストコードを実行するまでにも時間がかかってしまいました。本記事が、自動テスト環境構築の一助になれば幸いです。


株式会社ONE WEDGE

【Serverlessで世の中をもっと楽しく】
ONE WEDGEはServerlessシステム開発を中核技術としてWeb系システム開発、AWS/GCPを利用した業務システム・サービス開発、PWAを用いたモバイル開発、Alexaスキル開発など、元気と技術力を武器にお客様に真摯に向き合う価値創造企業です。
https://onewedge.co.jp/

GitHubで編集を提案

Discussion