---
title: "Laravelのテスト自動化をDuskで実装する方法｜インストールからCI実行まで"
url: "https://www.issoh.co.jp/tech/details/5648/"
published: 2025-03-04
updated: 2026-07-17
categories: ["Laravel"]
publisher: "株式会社一創"
---

# Laravelのテスト自動化をDuskで実装する方法｜インストールからCI実行まで

Laravelのテスト自動化は、大きく**単体・機能テスト（PHPUnit／Pest）**と**ブラウザE2Eテスト**の2層に分かれます。前者はコードから直接ロジックやHTTPレスポンスを検証し、後者は実際のブラウザを操作して「ユーザーが画面で行う操作」そのものを自動化します。このブラウザ層を担う公式ツールが**Laravel Dusk**です。本記事は、Duskを使ったブラウザテスト自動化に絞って、全体像・インストール・テストの書き方・待機とアサート・GitHub ActionsでのCI実行・Pest 4との使い分けまでを一気通貫で解説します。単体・機能テストの書き方は[PestPHPとは？シンプルで読みやすいPHPテストフレームワークの概要](/tech/details/7255/)で扱っているため、本記事では重複せずブラウザ操作の自動化に集中します。バージョンはDusk v8.6.0（2026年4月時点、PHP 8.1以上・Laravel 10〜13対応）を前提とします。

## まとめ：Laravel Duskによるテスト自動化の要点

- Laravelのテスト自動化は「単体／機能テスト（PHPUnit・Pest）」と「ブラウザE2Eテスト（Dusk）」の2層。Duskは実ブラウザ（Chrome）を操作するE2E担当。
- 導入は `composer require laravel/dusk --dev` と `php artisan dusk:install` の2コマンド。ChromeDriverは自動で用意される。
- 要素の指定はCSSセレクタより **dusk属性**（テスト側は `@` 接頭辞）で安定させる。
- 動的ページでは **待機処理**（`waitFor`／`waitForText`／`whenAvailable`）が安定の鍵。
- CIはGitHub ActionsでChromeDriver起動→`php artisan serve`→`php artisan dusk` の順に実行する。
- 新規プロジェクトは公式が**Pest 4のブラウザテスト**を推奨。既存資産や特定要件がある場合にDuskを選ぶ、という判断軸で使い分ける。

以降で、テスト自動化の全体像におけるDuskの位置づけから、具体的な実装とCI運用までを順に見ていきます。

## Laravelのテスト自動化の全体像とDuskの位置づけ

「Laravel テスト自動化」と一口に言っても、検証する対象によって使うツールが変わります。まず全体像を押さえると、Duskをどこで使うべきかが明確になります。Laravelのテストは概ね次の3層に整理できます。

| 層          | 検証対象                 | 主なツール          | ブラウザ          |
| ---------- | -------------------- | -------------- | ------------- |
| 単体テスト      | クラス・メソッド単体のロジック      | PHPUnit / Pest | 不要            |
| 機能テスト      | HTTPリクエストとレスポンス・DB状態 | PHPUnit / Pest | 不要            |
| ブラウザE2Eテスト | 画面操作・JavaScript込みの挙動 | Laravel Dusk   | 実ブラウザ(Chrome) |

単体・機能テストは、LaravelがカーネルをPHPプロセス内で起動して直接リクエストを流すため**ブラウザを起動しません**。高速で、CIでも軽く回せます。一方、Vue・React・AlpineなどのJavaScriptで動く画面や、フォーム送信後のリダイレクト、モーダル表示といった「実際に描画された結果」は、PHPプロセス内のテストでは検証できません。ここを埋めるのがDuskです。Duskは実際のChromeを立ち上げ、人間と同じようにクリック・入力・待機を行います。

したがって使い分けの判断はシンプルです。**ロジックとAPIレスポンスは機能テスト（Pest／PHPUnit）で数多く速く、画面全体の動作確認だけをDuskで少数に絞る**のが定石です。E2Eは実行が重く壊れやすいため、全画面をDuskで網羅しようとすると保守コストが跳ね上がります。単体・機能テストの具体的な書き方は[PestPHPの概要記事](/tech/details/7255/)にまとめています。

## Laravel Duskとは──実ブラウザを操作するE2Eテストツール

Laravel Duskは、Laravel公式が提供するブラウザ自動化・E2Eテスト用パッケージです。特徴は、テスト実行時に**ChromeDriver経由で実際のGoogle Chromeを起動**し、指定したURLを開いてクリックや入力を自動で行う点にあります。Seleniumのように別途Javaの実行環境や外部サーバーを用意する必要がなく、`php artisan dusk:install` がChromeDriverのバイナリまで含めて環境を整えてくれるため、LaravelプロジェクトにComposerで追加するだけでブラウザテストを始められます。

Duskで自動化できるのは、たとえばログインフォームに入力して送信し遷移先を確認する、モーダルが表示されるまで待ってボタンを押す、JavaScriptで動的に増える要素の件数を検証する、といった**「画面越しのユーザー操作」全般**です。テスト失敗時には自動でスクリーンショットを保存するため、CI上で落ちたときの原因調査もしやすくなっています。

## Laravel Duskのインストールと初期設定

### Composerでの導入とdusk:install

Duskはテストにのみ使うため、開発依存として追加します。追加後に `dusk:install` を実行すると、`tests/Browser` ディレクトリ・サンプルテスト・`DuskTestCase` 基底クラス・OSに合ったChromeDriverが一括で用意されます。

```
composer require laravel/dusk --dev
php artisan dusk:install
```

導入後は、テストがアクセスする先を `.env` の `APP_URL` に合わせておきます（例: `http://127.0.0.1:8000`）。Duskはここに書かれたURLを基準に `visit` の相対パスを解決するため、実際に `php artisan serve` で起動するアドレスと一致していないと、`visit` の解決先がずれてテストが失敗します。

### テスト専用の環境分離（.env.dusk）とChromeDriver更新

本番・開発用のDBをテストで壊さないよう、Dusk専用の環境ファイルを用意できます。`.env.dusk.local` のように `.env.dusk.{環境名}` を置くと、Duskは実行時に既存の `.env` を退避してこちらを読み込み、終了後に元へ戻します。テスト用DBを分けておくと安全です。

```
APP_URL=http://127.0.0.1:8000
APP_ENV=dusk
DB_DATABASE=dusk_database
```

Chrome本体は自動更新で新しくなるため、ChromeDriver側とバージョンがずれると起動に失敗します。ずれた場合は、インストール済みChromeのバージョンを検出して合わせる次のコマンドで解消します。

```
php artisan dusk:chrome-driver --detect
```

## Duskテストの書き方──基本構造とブラウザ操作

### テストクラスの基本構造とデータベース

Duskテストは `DuskTestCase` を継承し、`browse` メソッドに渡したクロージャの中で `Browser` インスタンスを操作します。テストごとにDBを初期化するには `DatabaseMigrations` または、より高速な `DatabaseTruncation` トレイトを使います。なお**Duskは別プロセスでブラウザを動かすため、SQLiteのインメモリDBは利用できません**（プロセス間で共有されないため）。ファイルベースのテスト用DBを使ってください。

```
<?php

namespace Tests\Browser;

use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTruncation;
use Laravel\Dusk\Browser;
use Tests\DuskTestCase;

class LoginTest extends DuskTestCase
{
    use DatabaseTruncation;

    public function test_user_can_login(): void
    {
        $user = User::factory()->create([
            'email' => 'taylor@laravel.com',
        ]);

        $this->browse(function (Browser $browser) use ($user) {
            $browser->visit('/login')
                ->type('email', $user->email)
                ->type('password', 'password')
                ->press('Login')
                ->assertPathIs('/home');
        });
    }
}
```

### ページ操作の基本メソッド

ブラウザ操作はメソッドチェーンで記述します。よく使うのは遷移の `visit`／`visitRoute`、入力の `type`／`select`／`check`、実行の `press`（ボタン）／`clickLink`（リンク文字列）です。フォームを埋めて送信し、結果ページを検証する、という一連の流れを自然に書けます。

```
$browser->visit('/register')
    ->type('name', 'Taro')
    ->select('plan', 'pro')
    ->check('terms')
    ->press('Sign Up')
    ->assertPathIs('/dashboard');
```

### dusk属性でセレクタを安定させる

E2Eテストが壊れやすい最大の原因は、CSSクラスやテキストの変更でセレクタが外れることです。Duskは要素に専用の `dusk` 属性を付け、テスト側から `@` 接頭辞で参照する方法を推奨しています。デザイン変更でクラス名が変わってもテストが壊れません。

```
<button dusk="login-button">Login</button>
```

```
$browser->click('@login-button');
```

## 待機処理とアサーション──動的ページを安定してテストする

### 要素の出現を待つ待機メソッド

JavaScriptで後から描画される要素をすぐに操作しようとすると、まだ存在せずテストが失敗します。Duskは指定要素が現れるまで待つ `waitFor`、テキストが出るまで待つ `waitForText`、要素が現れてからその中を操作する `whenAvailable` などを備えます。既定の待機上限は5秒で、第2引数で秒数を変えられます。`pause` による固定待機は不安定になりやすいため、条件付きの待機を優先します。

```
$browser->waitFor('@server-list', 3)
    ->waitForText('Ready')
    ->whenAvailable('@confirm-modal', function ($modal) {
        $modal->assertSee('Are you sure?')->press('OK');
    });
```

### 結果を検証するアサーション

操作の結果は各種アサーションで確認します。表示文言は `assertSee`／`assertDontSee`、URLやパスは `assertPathIs`／`assertRouteIs`、ページタイトルは `assertTitle`、入力値やチェック状態は `assertInputValue`／`assertChecked`、ログイン状態は `assertAuthenticated` で検証できます。

```
$browser->assertPathIs('/home')
    ->assertSee('ようこそ')
    ->assertAuthenticated();
```

## ヘッドレスモードとGitHub ActionsでのCI自動化

### ヘッドレスモードの設定

CIサーバーには画面（GUI）がないため、Chromeを画面表示なしで動かす**ヘッドレスモード**で実行します。Duskでは `tests/DuskTestCase.php` の `driver` メソッドでChromeの起動オプションを指定し、`--headless=new` や `--disable-gpu`、コンテナ環境向けの `--no-sandbox` を渡します。ローカルでは画面ありで挙動を目視し、CIではヘッドレスにする、といった切り替えが一般的です。

### GitHub ActionsでのDuskテスト実行

CIでは「ChromeDriverを対象Chromeに合わせて更新」→「ChromeDriver起動」→「アプリをサーブ」→「Dusk実行」の順に組みます。GitHub Actionsのステップ例は次のとおりです。なおChromeDriverと `serve` はバックグラウンド起動のため、これらとDusk実行は**同一ジョブの連続ステップ**に置きます（別ジョブに分けるとバックグラウンドプロセスが引き継がれません）。継続的インテグレーション全体の組み方は[GitHub Actionsでビルド・自動テストを設定する方法｜CI/CDワークフローの作り方](/tech/details/2497/)で解説しています。

```
- name: Update Chrome Driver
  run: php artisan dusk:chrome-driver --detect
- name: Start Chrome Driver
  run: ./vendor/laravel/dusk/bin/chromedriver-linux --port=9515 &
- name: Run Laravel Server
  run: php artisan serve --no-reload &
- name: Run Dusk Tests
  env:
    APP_URL: "http://127.0.0.1:8000"
  run: php artisan dusk
```

## テストの実行・デバッグとスクリーンショット

テストは `php artisan dusk` で実行します。失敗したテストだけを再実行するなら `php artisan dusk:fails`、特定グループに絞るなら `--group` オプションを使います。`php artisan test` がPHPUnit／Pestのユニット・機能テストを回すのに対し、Duskは専用の `dusk` コマンドで動く点に注意してください。

```
php artisan dusk
php artisan dusk:fails
php artisan dusk --group=checkout
```

Duskはテスト失敗時に `tests/Browser/screenshots` へ自動でスクリーンショットを保存します。任意のタイミングで撮る `screenshot`、ブラウザのコンソールログを残す `storeConsoleLog`、HTMLソースを保存する `storeSource` を使うと、CI上でしか再現しない不具合の調査が容易になります。

```
$browser->screenshot('checkout-step1');
$browser->storeConsoleLog('checkout-console');
```

## DuskとPest 4ブラウザテストの選び方

2026年時点で、**Laravel公式ドキュメントは新規プロジェクトのブラウザテストにDuskではなくPest 4を推奨**しています。Pest 4はブラウザテスト機能を内蔵し、Duskより高速でAPIも簡潔だからです。とはいえ既存のDuskテストが直ちに動かなくなるわけではなく、Duskは引き続き保守されています。判断軸を整理します。

| 観点    | Laravel Dusk         | Pest 4 ブラウザテスト      |
| ----- | -------------------- | ------------------- |
| 公式の推奨 | (既存資産では継続が現実的)       | 新規プロジェクトに推奨         |
| 記法    | Browserメソッドチェーン      | Pestのit/expect構文    |
| ドライバ  | ChromeDriver(Chrome) | Playwright系(複数ブラウザ) |
| 導入コスト | dusk:installで完結      | Pest導入が前提           |

結論として、**これから書き始めるならPest 4のブラウザテストを第一候補**にすべきです。一方で、すでにDuskのテスト資産が積み上がっているプロジェクトや、`dusk:install` だけで完結する手軽さを重視する場合は、Duskを継続する判断も十分に合理的です。無理に全面移行するより、既存はDuskで維持し新規はPest 4で書く、という併存も現実的な選択肢です。Pest 4のブラウザテストの詳細は[Pest v4とは何か？概要と特徴を徹底解説【新機能・進化ポイントまで】](/tech/details/10349/)を参照してください。

## よくある質問

### Laravel Duskとは何ですか？

実際のGoogle Chromeを操作して画面越しのユーザー操作を自動化する、Laravel公式のブラウザE2Eテスト用パッケージです。`php artisan dusk:install` でChromeDriverまで含めて環境が整い、クリック・入力・待機・アサートをコードで記述してブラウザテストを自動実行できます。

### DuskとPHPUnit／Pestのテストは何が違いますか？

PHPUnitやPestの単体・機能テストはブラウザを起動せず、PHPプロセス内でロジックやHTTPレスポンスを高速に検証します。Duskは実ブラウザを起動し、JavaScript込みの画面挙動を検証するE2E層を担います。速いロジック検証はPest／PHPUnit、画面全体の動作確認だけをDuskに、と使い分けるのが基本です。

### DuskとPest 4のブラウザテストはどちらを使うべきですか？

新規プロジェクトは、公式が推奨するPest 4のブラウザテストが第一候補です。すでにDuskのテスト資産があるプロジェクトや、追加のPest導入なしに始めたい場合はDuskの継続が合理的です。既存はDusk・新規はPest 4という併存も可能です。

### ヘッドレスモードでテストが動かないときは？

まずChromeとChromeDriverのバージョンずれを `php artisan dusk:chrome-driver --detect` で解消します。コンテナやCIでは `--no-sandbox`／`--disable-gpu` オプションの付与、`APP_URL` と実際のサーブ先の一致、ChromeDriverの起動忘れがないかを確認してください。

### 日本語や多言語ページのテストはできますか？

可能です。`assertSee` に日本語文言をそのまま渡して検証でき、ロケールを切り替えた画面表示の確認もできます。言語切り替え後は要素が再描画されるため、`waitForText` で表示を待ってからアサートすると安定します。

## 関連記事

- [PestPHPとは？シンプルで読みやすいPHPテストフレームワークの概要](/tech/details/7255/)
- [Pest v4とは何か？概要と特徴を徹底解説【新機能・進化ポイントまで】](/tech/details/10349/)
- [GitHub Actionsでビルド・自動テストを設定する方法｜CI/CDワークフローの作り方](/tech/details/2497/)

---

出典: [Laravelのテスト自動化をDuskで実装する方法｜インストールからCI実行まで](<https://www.issoh.co.jp/tech/details/5648/>)（株式会社一創）
