「Laravel Dusk × GPT-4o」でブラウザテストを超効率化！最強ツールを紹介します

# はじめに
「テストを自動化したいけど、テストコードを書くのが面倒...」

「UIが変わるたびにテストコードの修正が大変...」

「エラーが起こって動かない...」

こんな悩みを持つ開発者の方も多いのではないでしょうか？本記事では、生成AIと Laravel Dusk を組み合わせて、ブラウザテストを超効率化するツールをご紹介します。

# 目次
1. Laravel のテスト自動化ツール
2. ブラウザテスト × 生成AI
3. 環境構築
4. テストケース生成
5. テスト実行
6. まとめ

前置きが不要な方は、3. 環境構築に進んでください。

# 1. Laravel のテスト自動化ツール
Laravel には、以下の２つのテスト自動化ツールが組み込まれています。

## ユニットテスト PHPUnit
ユニットテストは、アプリケーションの個々の部品を独立して検証するテスト手法です。Laravel では、PHPUnitがデフォルトのテストフレームワークとして組み込まれており、これにより開発者は単体テストを自動化し、コードの品質を向上させることができます。

[Laravel 11.x テスト](https://readouble.com/laravel/11.x/ja/testing.html)

## ブラウザテスト Laravel Dusk (WebDriver）
ブラウザテストは、Webアプリケーションの一連の流れを検証するE2E（End to End）テストの一種です。Laravel Dusk は、Laravelフレームワーク用に開発されたブラウザテスト自動化ツールで、WebDriver を利用して実際のブラウザ操作を自動化します。このツールを使えば、ボタンクリックやフォーム送信などのUI操作から、動的に変化する画面の検証まで、E2Eテストをスムーズに実行することができます。

[Laravel 11.x Laravel Dusk](https://readouble.com/laravel/11.x/ja/dusk.html)

## ユニットテストとブラウザテストの特徴
| | ユニットテスト | ブラウザテスト |
|--------------|--------------|--------------|
| テストスクリプト作成 | <font color='red'>X</font> 必要 | <font color='red'>X</font> 必要 |
| テスト実行 | <font color='blue'>O</font> 速い | <font color='red'>X</font> 遅い |
| クライアント処理のテスト | <font color='red'>X</font> ブラウザで実行しないので、JavaScriptなどのテストはできない | <font color='blue'>O</font> ブラウザで実行するので、JavaScriptなども含めてE2Eでテストができる |
| メンテナンス性（UI変更など） | <font color='blue'>O</font> ビジネスロジックの検証がメインのため、仕様変更の影響を受けにくい | <font color='red'>X</font> 要素の指定がシビアで、仕様変更の影響を受けやすい |

# 2. ブラウザテスト × 生成AI
デメリットもあるものの、JavaScript なども含めてE2Eでテストができるブラウザテストは非常に強力です。ブラウザテストのテストスクリプト作成とメンテナンス性の問題を、生成AI（GPT-4o）を活用して改善します。
| | ブラウザテスト | 改善の方向性 |
|--------------|--------------|--------------|
| テストスクリプト作成 | <font color='red'>X</font> 必要 | 自然言語からコードを自動生成 |
| テスト実行 | <font color='red'>X</font> 遅い | |
| クライアント処理のテスト | <font color='blue'>O</font> ブラウザで実行するので、JavaScriptなども含めてE2Eでテストができる | |
| メンテナンス性（UI変更など） | <font color='red'>X</font> 要素の指定がシビアで、仕様変更の影響を受けやすい | 「確認ボタン」や「検索フォーム」のような自然言語で要素を指定 |

## 自然言語からコードを自動生成
生成AIを使えば、ユーザーの操作内容を自然言語で指示することで、コードを自動生成できます。
例えば、この指示を書いた場合:
```php:tests/Browser/QiitaTest.php
    public function testQiita(): void
    {
        $this->browse(function (Browser $browser) {
            // qiita.comに移動する
            // 検索フォームにblocsと入力して、リターンする
            // 一番上の記事のリンクをクリックする
        });
    }
```

このようなコードを自動で生成してくれます。生成されたコードを実行するとブラウザテストができます。
```php:tests/Browser/QiitaTest.php
    public function testQiita(): void
    {
        $this->browse(function (Browser $browser) {
            // qiita.comに移動する
            $browser->visit('https://qiita.com');

            // 検索フォームにblocsと入力して、リターンする
            $browser->type('input[name="q"]', 'blocs')
                ->keys('input[name="q"]', \Facebook\WebDriver\WebDriverKeys::ENTER)
                ->pause(1000);

            // 一番上の記事のリンクをクリックする
            $browser->scrollIntoView('.style-1kxl4ny')
                ->clickLink('【Laravel】Template engine を作ってみた')
                ->pause(1000);
        });
    }
 ```


## 「確認ボタン」や「検索フォーム」のような自然言語で要素を指定 
生成AIが表示しているページのHTMLを解析し、自然言語で指定された入力欄の名前やボタンのCSSセレクターを取得します。これにより、「検索フォーム」や「確認ボタン」のような自然言語で要素を指定できます。UIが変更されてブラウザテストでエラーが発生した場合でも、指示を変更せずにコードを再生成するだけでエラーを解決できます。
例えば、このコードの場合:
```php:tests/Browser/QiitaTest.php
// 確認ボタンをクリックする、モーダル内の更新ボタンをクリックする
$browser->press('確認')
    ->waitFor('#modalUpdate')
    ->press('#modalUpdate .btn-primary');
```

ボタンのクラスが変更されても、UIに合わせてコードを生成してくれます。
```php:tests/Browser/QiitaTest.php
// 確認ボタンをクリックする、モーダル内の更新ボタンをクリックする
$browser->press('確認')
    ->waitFor('#modalUpdate')
    ->press('#modalUpdate .btn-secondary');
```

:::note info
生成AIで Laravel Dusk のコード生成をサポートするパッケージを開発しました。
:::
https://github.com/blocs/dusk

以下の3ステップだけで、ブラウザテストを超効率化できます。生成AIがサポートするのは、ステップ2（テストスクリプト作成）のみです。GPT-4o の利用にはトークンごとに費用がかかりますが、テストスクリプト作成が完了すれば、テスト実行にはコストがかかりません。
 - 環境構築
 - テストスクリプト作成
 - テスト実行

# 3. 環境構築
本パッケージを使用する際、テスト対象の Laravel プロジェクトに直接インストールする必要はありません。テスト対象のプロジェクトがブラウザからアクセス可能な状態（開発サーバーやステージング環境として起動している状態）であれば、テスト用 Laravel プロジェクトを別に構築し、そこからテストを実行することも可能です。

:::note info
テストコードの生成には LLM の利用が必要なため、お持ちでない場合は、OpenAI_API キーを取得してください。[OPENAI_APIキーの取得方法](https://qiita.com/kurata04/items/a10bdc44cc0d1e62dad3)
:::

## 必要な環境
- PHP 8.1 以上
- Composer
- Laravel 10 以上

## セットアップコマンド
### 1. テスト用 Laravel プロジェクト作成
```bash
composer create-project laravel/laravel [プロジェクト名]
例） composer create-project laravel/laravel dusk-web-test
```

### 2. blocs/dusk をインストール
```bash
cd dusk-web-test
composer require --dev blocs/dusk
```

### 3. Laravel Dusk と Open AI をインストール
```bash
php artisan dusk:install
php artisan openai:install
```

### 4. Laravel Dusk を実行
```bash
php artisan dusk
```

:::note alert
初回実行時にエラーが発生する場合があります。その場合は、再度実行してください。
:::

### 5. envの設定
```bash
OPENAI_API_KEY=your-api-key-here
```

以上で環境構築は完了です。


# 4. テストスクリプト作成
テストに関係するディレクトリ構造は以下の通りです。
```
dusk-web-test/
├─ config/
│   └─ openai.php/
├─ tests/
│   ├─ Browser/
│   │   ├─ ExampleTest.php
│   │   ├─ QiitaTest.php
│   │   ├─ blocs/
│   │   │   ├─ system.md
│   │   │   ├─ user.md
│   │   │   ├─ sample.md
│   │   │   └─ assistant.md
│   │   ├─ screenshots/
│   │   └─ ...（他のディレクトリは省略）
│   ├─ Feature/
│   ├─ Unit/
│   └─ DuskTestCase.php
└─ ...（他のディレクトリは省略）
```
ブラウザテストのテストスクリプト（ExampleTest.phpなど）は、tests/Browser 配下に配置します。tests/Browser/blocs 配下のファイルには、コード生成の役割が設定されています。サンプルコードなど、これらのファイルを編集することで、プロジェクトごとにコード生成の精度を向上させることができます。[OpenAI APIにおける「role」とは](https://zenn.dev/atusi/articles/b67a3f1a499880)

| ファイル | 役割 |
|--------------|----------|
| system.md | AIの振る舞いや態度など会話の全体的な文脈を指定 |
| user.md | 何をするか（タスク）や制約条件を指定、プロジェクトごとに適切な条件を設定することで、そのシステムに最適なコードを生成することができます |
| sample.md | サンプルコードを指定、コードの生成例や仕様を設定します |
| assistant.md | コードを生成する際のルールを指定 |

## 4.1 テストスクリプト準備
実行したい操作内容の指示をコメントで記載します。
```php:tests/Browser/ExampleTest.php
    public function testBasicExample(): void
    {
        $this->browse(function (Browser $browser) {
            // http://dev.local/loginに移動する
            // ID:admin, Password:adminを入力してログインする
            // サイドメニューの User のリンクをクリックする、リンクはCSSセレクターで指定する
            // 一覧画面から new ボタンをクリックする
            // userID に適当なemailを入力して、admin のチェックボックスをチェックする
            // password に適当なパスワードを入力、repassword に password と同じパスワードを入力する
            // Confirmボタンをクリックした後にsubmitボタンを押す
        });
    }
```

一つのテストスクリプトに複数のテストケースを入れることもできます。

```php:tests/Browser/QiitaTest.php
    private function testQiita($browser): void
    {
        $this->browse(function (Browser $browser) {
            // qiita.comに移動する
            // 検索フォームにblocsと入力して、リターンする
            // 一番上の記事のリンクをクリックする
        });
    }

    private function testYahoo($browser): void
    {
        $this->browse(function (Browser $browser) {
            // yahoo.co.jpに移動する
            // 入力フォームに生成AIと入力して、検索ボタンをクリック
            // ChatGPTが表示されていることを確認する
        });
    }
```

## 4.2 テストスクリプト作成
このコマンドで、サポートツールを実行します。サポートツールを実行するとコマンド選択が表示されます。（↑↓で選択可能です。）
```bash
php artisan blocs:dusk tests/Browser/ExampleTest.php
```

![image-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4023825/37bef8f9-1225-4037-af32-2822c1857497.png)

| コマンド | 説明 |
|--------------|----------|
| testXXX edit | 指定したテストケースのコードを生成する|
| run | 指定したテストスクリプトを実行する（Gpt-4o に問い合わせを行わない）|
| quit | 終了する|

テストケースのコード生成は、ステップごとに対話式で行います。ステップのコードがすでに生成されている場合、そのステップは自動で実行されます。まだコードが生成されていない場合は、コメントで指示した操作内容のコードを自動生成します。自動生成されたコードのコマンドを選択します。
![image-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4023825/24c54737-b13f-43c9-9299-780f8dcb3646.png)

| コマンド | 説明 |
|--------------|----------|
| execute | 生成したコードを実行する |
| retry | エラーが発生した時、同じコードで再実行する |
| 自由入力 | 追加で指示をしてコードを再生成します<br />例) ログインボタンを正しくCSSセレクターで指定してください |
| skip | このステップをとばす |
| quit | 自動生成を終了する |

全てのステップの自動生成が終わった後に、ステップを追加できます。

| コマンド | 説明 |
|--------------|----------|
| 自由入力 | 新しいステップを追加します<br />例）ログアウトする |
| quit | 自動生成を終了する |

### LLM モデルの指定
パッケージ導入時のデフォルト設定では、gpt-4o-mini と gpt-4o を組み合わせてコードを生成します。基本的には gpt-4o-mini を使用し、指示を追加してコードを再生成する場合に gpt-4o へ問い合わせを行います。使用するモデルを指定したい場合は、config/openai.php に記載します。このように指定した場合は、常に gpt-4o-mini を使用することになります。

```php:config/openai.php
'model' => 'gpt-4o-mini',
```

## 4.3 ドライラン
サポートツールの run コマンドを実行すると、テストのドライランを行えます。実際に実行してみると、このような感じです。

<iframe width="560" height="315" src="https://www.youtube.com/embed/mmViCMeAUbA?si=nxLtwr18etzlu3ff" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>


# 5. テスト実行
このコマンドを実行すると、Laravel Dusk　でテストスクリプトを実行します。Laravel Dusk　はヘッドレスモードでブラウザテストを実行するため、画面を表示せずにバックグラウンドで動作します。UI変更などの仕様変更が起こらない限り、このコマンドを実行することでリグレッションテストを行うことができます。テストスクリプトの修正が必要になった場合は、テストスクリプト作成に戻って修正してください。

```bash
php artisan dusk tests/Browser/ExampleTest.php
```

# 6. まとめ
本記事では、Laravel Dusk × GPT-4 でブラウザテストを超効率化するツールについて紹介しました。興味のある方は、ぜひ試してみてください！

## おわりに
弊社では、Laravel の開発をもっと便利にするテンプレートエンジンの開発も行っています。

- [BLOCS公式リファレンス](https://blocs.jp/)
- [【Laravel】Template engine を作ってみた](https://qiita.com/hyada/items/a0aec797d81469b15bf3)

# 参考文献
- [Laravel Dusk 公式ドキュメント](https://laravel.com/docs/dusk)
- [OpenAI APIリファレンス](https://platform.openai.com/docs/api-reference)