🎉

Pest v4 - Laravel E2Eテストの新スタンダード

に公開

概要

2025年7月29日(火)に開催された Laracon US 2025 DAY 1にて、Pest v4 が発表されました!

主な変更点は以下です。

  • Browserテスト機能の追加
  • Shardingオプション追加
  • Type Coverage機能高速化
  • Profanity checking(不適切な言葉の検出)機能の追加

発表の内容を簡単にまとめてみました!

Browserテスト機能の追加

概要

E2Eテストフレームワークの中でデファクトスタンダードとも言える、PlaywrightをベースにしたBrowserテスト機能が導入されます。

PestでFeatureテストは以下のように書きます。

test('home page', function() {
    $response = $this->get('/');

    $response->assertStatus(200);
})

Pest Browserテストでは以下のように書きます。

test('home page', function() {
    $response = visit('/');

    $response->assertSee('Laravel');
})

「ログインページにアクセスして、メールアドレスとパスワードを入力して、ログインボタンを押下して、遷移したページにDashboardが表示される。」
というE2Eテストを以下のように書けます。

test('login', function() {
    $user = User::factory()->create();

    visit('/')
        ->click('Log in')
        ->type('email', $user->email)
        ->type('password', 'password')
        ->press('Log in')
        ->assertSee('Dashboard');
})

既存のUnitテスト、Featureテストと同様に

./vendor/bin/pest

でテストの実行が可能です。

EloquentなどのLaravelの機能を使いつつE2Eテストが書けるのはとてもいいですね、、!
その他、以下のメリットもあるようです。

  • SQLiteのインメモリDBの使用が可能で高速
  • リダイレクト後の遷移待機 (waitForText など)が不要

Laravelテスト用ヘルパーの併用

Laravelテストではお馴染みの以下のようなfake系テスト用ヘルパーも使えます。

test('login', function() {
    Notification::fake();
    $user = User::factory()->create();

    visit('/')
        ->click('Log in')
        ->type('email', $user->email)
        ->type('password', 'password')
        ->press('Log in')
        ->assertSee('Dashboard');
    Notification::assertSentTo($user, LoginNotification::class);
})

コードカバレッジ対応

従来のようにcoverageオプションをつけて実行するだけでブラウザテストとユニットテストを含めたコードカバレッジの取得が可能です。

./vendor/bin/pest --coverage

デバッグ機能

debug()

メソッドが呼ばれた時点の状態でブラウザが起動し、視覚的に問題箇所を確認可能です。

test('login', function() {
    $user = User::factory()->create();

    visit('/')
        ->click('Log in')
        ->type('email', $user->email)
        // ->type('password', 'password')
        ->press('Log in')
        ->debug()
        ->assertSee('Dashboard');
})

tinker()

メソッドが呼ばれた時点の状態でTinkerセッションを起動して、リクエスト情報などを確認可能です。

test('login', function() {
    $user = User::factory()->create();

    visit('/')
        ->click('Log in')
        ->type('email', $user->email)
        ->type('password', 'password')
        ->press('Log in')
        ->assertSee('Dashboard')
        ->tinker();
})

tinkerが起動

ログインユーザー情報を確認できる

スモークテストの強化

従来のスモークテスト

ステータスコードが200であることを確認するのが主流でした。

test('smoke', function() {
    $user = User::factory()->create();

    $this->actingAs($user);

    $routes = [
        '/',
        '/dashboard',
        '/settings/profile',
    ];

    foreach ($routes as $route) {
        $response = $this->get($route);

        $response->assertStatus(200);
    }
});

ブラウザテストを使ったスモークテスト

ブラウザテストを使うことで、ステータスコードだけでなく、JavaScriptエラーやconsole.logの削除忘れを検出できます。

JavaScriptエラーがないかの確認

    foreach ($routes as $route) {
        $response = visit($route);

        $response->assertNoJavaScriptErrors();
    }

console.log()が残っていないかの確認

    foreach ($routes as $route) {
        $response = visit($route);

        $response->assertNoJavaScriptErrors()
                ->assertNoConsoleLogs();
    }

複数ルート配列に対してforeachなしで記述可能

test('smoke', function() {
    $user = User::factory()->create();

    $this->actingAs($user);

    $routes = [
        '/',
        '/dashboard',
        '/settings/profile',
    ];

    visit($routes)->assertNoJavaScriptErrors()
                ->assertNoConsoleLogs();
});

assertNoSmokeassertNoJavaScriptErrors()asserNoConsoleLogs()を同時に行える

test('smoke', function() {
    $user = User::factory()->create();

    $this->actingAs($user);

    $routes = [
        '/',
        '/dashboard',
        '/settings/profile',
    ];

    visit($routes)->assertNoSmoke();
});

Visual Regressionテスト(画像回帰テスト)

概要

画面のスクリーンショットを撮り、画面の崩れが起きていないか確認できます。

visit($routes)->assertScreenshotMatches();

初回にスクリーンショットを保存、2回目以降に差分を比較し、差分がなければpassする

./vendor/bin/pest --diff オプションでビジュアルに差分を確認可能なツールが使えます(スライダーを使って新旧比較できる)

デバイス・テーマ対応

以下のように特定のデバイスの画面サイズやダークモードを指定してテスト可能です

visit($routes)
    ->on()->iphone15()
    ->inDarkMode()
    ->assertScreenshotMatches();

並列実行による高速化

PlaywrightとPest双方の並列実行により、テストの実行時間が大幅に短縮されています。
以下が同じテスト群をLaravel Dusk, PestT v4で実行した場合の実行時間の比較

ツール 実行時間
Laravel Dusk 約10秒
PEST v4 約2秒

その他の変更点

Sharding(CI上での分割実行)

GitHub Actionsなどで長時間かかるテストスイートを複数に分割し、同時実行することで高速化が可能になります。

strategy:
  matrix:
    shard: [1, 2, 3, 4, 5]

name: Tests (Shard ${{ matrix.shard }}/5)

steps:
    - name: Run tests
      run: pest --parallel --shard ${{.matrix.shard }}/5

Laravel CloudのコードベースのCIでは10分→2分に短縮されたそうです。。

Type Coverage改善

初回計測が約2倍高速化、2回目以降は即時取得可能に!

Profanity Checking

不適切語の検出機能が追加されるようです。

リリース時期

正式リリース予定日
2025年8月21日(Laravel Live Denmarkにて)

β版はそれ以前に公開予定とのことです

所感

型カバレッジ・アーキテクチャテスト・ミューテーションテストなどPHPUnitにはない機能を搭載してきたPestでしたが、Playwrightを使ったブラウザテスト機能は最後のピースを埋めてきた感があります!
LaravelアプリケーションのE2Eテストコードを作っていくときの有力候補になりそうですね💡
※逆にLaravel Duskを選定する理由はもうない気がしますね

記事の内容に誤りなどありましたらコメントいただけますと幸いです🙏

Nuno Maduro氏による発表(28:25~)
https://www.youtube.com/watch?v=_eMBogMlShs&t=3341s

Discussion