🧪

LaravelのテストをPestに乗り換えた理由と導入メモ

に公開

はじめに

こんにちは、田中涼平(@RyoheiTanaka)です。

健康管理アプリのバックエンド(GitHub リポジトリはこちら)を実装した際、API の構築を優先していたため、当初はテストコードを用意していませんでした。

リリース後のリファクタリングにおいて、動作保証と効率向上のためにテストを導入することにしました。

本記事では、Laravel に Pest を導入した際の流れや詰まったポイントをまとめます。


Pest を選んだ理由

業務では PHPUnit を使ってテストコードを書いていますが、個人開発で最新の Laravel を触っていた際に「Pest」というテストフレームワークを知りました。

  • コードが読みやすく、テスト結果のレポートも見やすい
  • 並列テストやテストの再実行、変更のあったテストだけを対象にするオプションなど、便利な機能が多い

といった理由から、試しに導入してみることにしました。


Pest の導入手順

要件

  • PHP 8.2 以上

インストール手順

  1. PHPUnit を削除
composer remove phpunit/phpunit
  1. Pest をインストール
composer require pestphp/pest --dev --with-all-dependencies
  1. Pest の初期化
./vendor/bin/pest --init
  1. テスト実行
./vendor/bin/pest

よく使いそうなオプション

--bail

最初のエラーまたは失敗でテストスイートの実行を停止します。

./vendor/bin/pest --bail

--dirty

Git 上でコミットされていない変更に関連するテストだけを実行します。全体テストを走らせたくないときに便利です。

./vendor/bin/pest --dirty

※PHPUnit 構文で書かれたテストケースは常に実行されます。


--retry

過去に失敗したテストを優先して実行します。失敗履歴がない場合は通常通り実行されます。

./vendor/bin/pest --retry

phpunit.xml に複数のテストスイート(例:Unit と Feature)がある場合、それぞれの中で並べ替えが行われます。


テスト用の DB 設定

そのまま実行すると開発用 DB に影響してしまうため、テスト用にインメモリの SQLite を使用します。高速で処理でき、扱いやすいため今回の用途に合っていました。

.env.testing を用意する場合

cp .env .env.testing
DB_CONNECTION=sqlite
DB_DATABASE=:memory:

phpunit.xml を変更する場合

<php>
    <env name="APP_ENV" value="testing"/>
    <env name="DB_CONNECTION" value="sqlite"/>
    <env name="DB_DATABASE" value=":memory:"/>
    <env name="APP_KEY" value="base64:xxxxxxxxxxxxxxxxxxxxxxxxxxx="/>
</php>

phpunit.xml だけで完結できるけど APP_KEY を Git 管理するの避けたほうがいい

テスト実行コマンド

./vendor/bin/pest --env=testing

マイグレーションが必要な場合

テストコード内に以下を記述します:

uses(RefreshDatabase::class);

サンプルテストコード

<?php

use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Hash;

uses(RefreshDatabase::class);

it('can login', function () {
    User::create([
        'name' => 'Test User',
        'email' => 'test@example.com',
        'password' => Hash::make('password'),
    ]);

    $this->get('/sanctum/csrf-cookie');

    $this->post('/login', [
        'email' => 'test@example.com',
        'password' => 'password',
    ])->assertStatus(200);
});

詰まったポイント

当初、Docker コンテナ内でテストを実行していましたが、テスト用の DB に接続されず苦戦しました。いったんホストマシン側で実行することで問題を回避しました。


今後の課題

  • Docker コンテナ内でもテストを実行できるよう調整したい
  • ホストマシン側の PHP バージョンが 8.4、Docker 内は 8.2 であるため、バージョンを揃えたい
  • プロジェクトごとにホストマシンの PHP バージョンを固定する方法があれば知りたい

まとめ

Pest は初めて使用しましたが、書き方がシンプルで、実行結果も見やすくとても扱いやすかったです。特に、SQLite のインメモリを使ったテストの実行速度には驚きました。

本記事が、Pest の導入を検討している方の参考になれば幸いです。


🚀 田中涼平の他の活動

Discussion