【自動化】playwright-mcpを駆使し、ソフトウェアテストの設計から実行、テスト結果の出力までの自動化を試みる

こんにちわ。GS です。

今回は、playwright-mcp を駆使して、AI を活用したソフトウェアテストの設計から実行、結果の出力に至るまでの様々な工程の自動化を試みていきます。

キーとなる技術は、

  • MCP
  • Playwright
    • Aria snapshots
  • LLM

の3つです。

前知識

まずは今回使用する技術や概念について説明します。

MCP(model context protocol)とは

MCP は「Model Context Protocol」の略で、AI モデル(LLM)が外部のデータソースやツールと通信するための標準化されたプロトコルです。

MCP をわかりやすく説明すると

MCP は、「AI のための USB-C」のようなものと考えてください。

例えば、あなたが持っている様々な家電(テレビ、スピーカー、照明、コーヒーマシンなど)を 1 つのリモコンで操作できるユニバーサルリモコンをイメージしてください。MCP は AI アシスタントにとってのそのユニバーサルリモコンです。

従来、AI モデル(ChatGPT、Claude、LLaMA など)が外部のシステム(データベース、API、社内文書など)と連携するには、それぞれのシステムごとに専用の接続方法を開発する必要がありました。これは、テレビ、エアコン、照明器具などにそれぞれ別のリモコンが必要なようなものです。

MCP はこの問題を解決し、AI モデルと外部ツールの間の「共通言語」を提供します。これにより:

  1. 開発者は各 AI モデルと外部ツールの組み合わせごとに独自の連携方法を作る必要がなくなります
  2. ユーザーは AI アシスタントに「今日のサンフランシスコの天気は?」と聞くだけで、AI が適切な外部ツールを使って最新情報を取得できます
  3. 新しいツールやデータソースを簡単に AI システムに追加できるようになります

2024 年末に Anthropic によって公開された MCP は、オープンスタンダードとして急速に普及し、多くの開発者がさまざまなツールやサービスと AI を連携させるためのサーバーを開発しています。

Playwright とは

Playwright は、Microsoft が開発したブラウザ自動化ツールです。 簡単に言うと、人間がブラウザで行う操作(ウェブサイトを開く、ボタンをクリックする、テキストを入力するなど)をコンピュータが自動的に行えるようにするソフトウェアです。 例えば、オンラインショッピングサイトで商品を検索したり、フォームに情報を入力したり、ログインしたりといった作業を、人間が手動でやる代わりに自動的に実行できます。 これは特にウェブサイトのテストや、繰り返し行う作業の自動化に役立ちます。

playwright-mcp とは

playwright-mcp は、Microsoft の Playwright チームが開発した MCP(Model Context Protocol)サーバーで、AI アシスタントがウェブブラウザを操作できるようにするツールです。このサーバーは、構造化されたアクセシビリティスナップショットを通じてウェブページとの対話を可能にし、スクリーンショットや視覚ベースのモデルを必要としない特徴があります。

playwright-mcp の主な機能

playwright-mcp の主な特徴は以下の通りです:

  • 高速で軽量:Playwright のアクセシビリティツリーを使用し、ピクセルベースの入力に依存しません
  • LLM フレンドリー:視覚モデルを必要とせず、純粋に構造化データで動作します
  • 決定論的なツール適用:スクリーンショットベースのアプローチでよくある曖昧さを回避します

playwright-mcp を使用すると、AI アシスタント(Claude や GPT-4 など)は以下のようなウェブブラウザの操作を行うことができます:

  • ウェブページの閲覧・ナビゲーション
  • テキスト入力やボタンのクリック
  • ページ内の要素の検索と情報取得
  • フォームの入力と送信
  • 構造化されたコンテンツからのデータ抽出

Aria Snapshot とは

Aria Snapshot は、Playwright が提供するウェブページのアクセシビリティ構造をテストするための機能です。この機能は、HTML の構造をアクセシビリティツリーの YAML 表現として提供し、ページの状態を検証するために使用されます。

特徴

  1. アクセシビリティツリーの表現: Aria Snapshot は、DOM の構造ではなく、アクセシビリティツリーを基にしています。これには要素の役割、名前、状態などの情報が含まれます。
  2. YAML 形式: スナップショットは YAML 形式で表現され、人間にも読みやすい形式で保存されます。
  3. 柔軟な比較: 部分的なマッチングや正規表現を使用した比較が可能で、動的なコンテンツにも対応できます。

強み

  1. リファクタリング耐性: DOM の内部構造が変更されても、アクセシビリティツリーは変わりにくいため、リファクタリングに強いテストが可能です。
  2. アクセシビリティの検証: アクセシビリティの観点からページ構造を検証できるため、支援技術との互換性を確保しやすくなります。
  3. 視覚に依存しないテスト: 見た目ではなく、構造的な変更を検出できるため、CSS の変更などに影響されにくいテストが可能です[1]。

弱み

  1. 詳細な視覚的テストには不向き: レイアウトや色などの視覚的な要素のテストには適していません。
  2. 学習コスト: アクセシビリティツリーの概念を理解する必要があり、初心者には難しい場合があります。

他の技術との違い

  1. 従来の DOM スナップショットとの違い: DOM の構造ではなく、アクセシビリティツリーを比較するため、内部実装の変更に強いテストが可能です。
  2. ビジュアルリグレッションテストとの違い: 視覚的な差異ではなく、構造的な差異を検出するため、異なる目的で使用されます。

YAML 表現の例

以下は、シンプルな HTML とそれに対応する Aria Snapshot(YAML 表現)の例です:

HTML:

<nav>
  <ul>
    <li><a href="/">ホーム</a></li>
    <li><a href="/about">概要</a></li>
    <li><a href="/contact">お問い合わせ</a></li>
  </ul>
</nav>

Aria Snapshot(YAML 表現):

- navigation:
    - list:
        - listitem:
            - link "ホーム"
        - listitem:
            - link "概要"
        - listitem:
            - link "お問い合わせ"

この例では、ナビゲーション構造がアクセシビリティツリーとして表現されており、各要素の役割と名前が明確に示されています。

playwright-mcp での活用

playwright-mcp では、この Aria snapshots を活用することで、AI アシスタントがウェブページの構造を理解し、適切な操作を行うことができます。視覚的な情報に依存せず、構造化されたデータのみを使用するため、軽量かつ高速な処理が可能になり、テキストベースの LLM でも効果的にウェブブラウザを操作できるという大きな利点があります。

使用例

playwright-mcp の典型的な使用例には以下のようなものがあります:

  1. ウェブナビゲーションとフォーム入力
  2. 構造化されたコンテンツからのデータ抽出
  3. LLM による自動テスト
  4. エージェントのための汎用ブラウザ操作
  5. バックグラウンドまたはバッチ操作(ヘッドレスモード)

導入方法

playwright-mcp は、npm 経由で簡単に導入できます。以下は基本的な設定例です:

{
  "mcpServers": {
    "playwright": {
      "command": "npx",
      "args": ["@playwright/mcp@latest"]
    }
  }
}

ヘッドレスモード(GUI なしのブラウザ)で実行する場合は以下のように設定します:

{
  "mcpServers": {
    "playwright": {
      "command": "npx",
      "args": ["@playwright/mcp@latest", "--headless"]
    }
  }
}

実行前準備

MCP サーバーを起動する方法は色々ありますが、今回使用する playwright-mcp サーバーをローカルの Node.js を使用して起動してみます。

Node.js そのもののインストール方法についての詳しい説明は割愛します。ちなみに筆者は Windows も Mac も mise を使ってインストールしています。

mise use -g node@lts

npx コマンドの確認

Node.js がインストールされていれば、以下のコマンドで npx コマンドが使用できるはずです。

npx --version

npx コマンドのパス確認

npx コマンドのパスを確認します。

Mac の場合

which npx

Windows の場合

where npx

操作ツール

MCP サーバーを呼び出せるツールなら何でもいいのですが、今回は Claude のデスクトップアプリ を使ってみます。

Claude Desktop の設定画面より、構成を編集を押します。

claude_desktop_config.json をお好きなエディタで開きましょう。

開いたファイルに以下の内容を追記します。今回設定する MCP サーバーは、アクセシビリティスナップショットを用いて操作をおこなう MCP サーバーです。

{
  "mcpServers": {
    "playwright": {
      "command": "npx",
      "args": ["@playwright/mcp@latest"]
    }
  }
}

設定が完了したら、Claude Desktop を再起動します。

正しく設定されていると、以下のように MCP サーバーが追加されているのが確認できるはずです。

設定がうまくいかない場合、command の部分をフルパスにすることで解消する可能性があります。

たとえば mise を使ってインストールした Node.js に付随する npx コマンドのパスは

Mac の場合

    "command": "/Users/{ユーザー名}/.local/share/mise/installs/node/22.14.0/bin/npx"

Windows の場合

    "command": "C:\Users\{ユーザー名}\scoop\apps\mise\current\mise\installs\node\22.14.0\npx.cmd"

のようなパスになります。 

●ヒント
MCP を使える MCP クライアントにはどんなものがある?
・ Visual Studio Code
・ Cursor
・ Visual Studio Code や Cursor で使える拡張機能の一つである Cline
・ 自作した MCP クライアント
など様々な選択肢があります。

playwright-mcp の実行

実際に実行して、様々な動作を確認しながら、テストに活用できる具体例を紹介します。

MCP サーバーに実行してほしい操作を伝えると、指示通りに実行されます。

実行時には、「この操作を本当に実行してもよいですか?」といった確認メッセージが表示されることがあります。

「このチャットで許可」を選択すると、同じ種類の操作については以降確認なしで自動的に実行されるようになります。

ウェブサイトの構造を確認してみよう

まずは MCP サーバーにウェブサイトの構造を確認してもらい、正しく動作していることを確認してみましょう。

以降 Web サイトに対する操作は、弊社サイト「Sqripts」を対象とします。

以下の命令を与えると、サイトの構造を tree コマンド形式で出力してくれます。

https://sqripts.com

このサイトの構造をtreeコマンド形式で出力してください。

このように、サイトの構造を tree コマンド形式で出力してくれます。

テストケースを生成してみよう

サイトの構造を確認したところで、テストケースを生成してみましょう。 今回はトップページだけのテストケースを生成してみます。

https://sqripts.com

このページの内容から、このページのためのテストケースを生成してください。

以下が実際に生成されたテストケースのマークダウンです。

# Sqripts.com のテストケース

## 1. ナビゲーションとリンクテスト

|ID|テスト項目|前提条件|テスト手順|期待結果|
|---|---|---|---|---|
|1.1|ヘッダーナビゲーションリンクの動作確認|Sqripts.comのトップページにアクセスする|1. 各ナビゲーションリンク(テクノロジー、品質、エンジニアリング、スクリプター、特集、ニュース、資料ダウンロード、Sqriptsについて)をクリックする|各リンクをクリックすると対応するページに正しく遷移する|
|1.2|「新規登録・ログイン」リンクの動作確認|Sqripts.comのトップページにアクセスする|1. 「新規登録・ログイン」リンクをクリックする|ログインページに正しく遷移する|
|1.3|フッターリンクの動作確認|Sqripts.comのトップページにアクセスする|1. フッター内の全てのリンクを一つずつクリックする|各リンクが正しく対応するページに遷移する|
|1.4|記事カテゴリタグリンクの動作確認|任意の記事ページを開く|1. 記事に付与されているカテゴリタグ(品質、エンジニアリング、ソフトウェアテストなど)をクリックする|対応するカテゴリページに正しく遷移する|

## 2. コンテンツ表示テスト

|ID|テスト項目|前提条件|テスト手順|期待結果|
|---|---|---|---|---|
|2.1|おすすめ記事セクションの表示確認|Sqripts.comのトップページにアクセスする|1. 「RECOMMEND おすすめ記事」セクションを確認する|おすすめ記事が正しく表示され、タイトル、日付、カテゴリ、著者情報が表示されている|
|2.2|最新記事セクションの表示確認|Sqripts.comのトップページにアクセスする|1. 「LATEST 最新記事」セクションを確認する<br>2. 複数の記事が表示されていることを確認する|複数の最新記事がサムネイル画像、タイトル、日付、カテゴリ、著者情報と共に表示されている|
|2.3|ランキングセクションの表示確認|Sqripts.comのトップページにアクセスする|1. 「RANKING アクセスランキング」セクションを確認する|人気記事が順位付けされて表示されている|
|2.4|著者情報の表示確認|任意の記事ページを開く|1. 記事内の著者情報(名前、画像)を確認する|著者の名前と画像が正しく表示されている|
|2.5|記事本文の表示確認|任意の記事ページを開く|1. 記事のタイトル、日付、カテゴリ、本文を確認する|記事の全コンテンツが正しく表示されている|

## 3. 機能テスト

|ID|テスト項目|前提条件|テスト手順|期待結果|
|---|---|---|---|---|
|3.1|「もっと見る」ボタンの動作確認|Sqripts.comのトップページにアクセスする|1. 最新記事セクション下部の「もっと見る」リンクをクリックする|記事一覧ページに正しく遷移し、より多くの記事が表示される|
|3.2|タグによる記事絞り込み機能確認|Sqripts.comのトップページにアクセスする|1. 「#TAGS 人気のタグ」セクションから任意のタグ(例:「AI」「ソフトウェアテスト」)をクリックする|選択したタグに関連する記事のみが表示されるページに遷移する|
|3.3|イベント・ニュースバナーの確認|Sqripts.comのトップページにアクセスする|1. 「EVENT・NEWS」セクションのバナーをクリックする|バナーに対応するイベントページやニュースページに正しく遷移する|

## 4. レスポンシブデザインテスト

|ID|テスト項目|前提条件|テスト手順|期待結果|
|---|---|---|---|---|
|4.1|モバイル表示確認|モバイルデバイスまたはブラウザの開発者ツールでモバイル表示を有効にする|1. Sqripts.comのトップページを表示する<br>2. 画面をスクロールし、各セクションの表示を確認する|全てのコンテンツがモバイル画面に適切に表示され、レイアウトが崩れない|
|4.2|タブレット表示確認|タブレットデバイスまたはブラウザの開発者ツールでタブレット表示を有効にする|1. Sqripts.comのトップページを表示する<br>2. 画面をスクロールし、各セクションの表示を確認する|全てのコンテンツがタブレット画面に適切に表示され、レイアウトが崩れない|
|4.3|画面回転時の表示確認|モバイルデバイスまたはブラウザの開発者ツールでモバイル表示を有効にする|1. Sqripts.comのトップページを表示する<br>2. 画面を横向きに回転させる|横向き表示でもコンテンツが適切に表示される|

## 5. パフォーマンステスト

|ID|テスト項目|前提条件|テスト手順|期待結果|
|---|---|---|---|---|
|5.1|トップページの読み込み速度確認|ブラウザの開発者ツールを開く|1. 開発者ツールのNetworkタブを有効にする<br>2. Sqripts.comのトップページをリロードする<br>3. 読み込み完了時間を確認する|ページの読み込み時間が3秒以内である|
|5.2|画像の最適化確認|ブラウザの開発者ツールを開く|1. 開発者ツールのNetworkタブを有効にする<br>2. Sqripts.comのトップページをリロードする<br>3. 画像ファイルのサイズを確認する|画像が適切に最適化されており、大きなファイルサイズの画像がない|
|5.3|記事ページの読み込み速度確認|ブラウザの開発者ツールを開く|1. 開発者ツールのNetworkタブを有効にする<br>2. 任意の記事ページを開く<br>3. 読み込み完了時間を確認する|記事ページの読み込み時間が3秒以内である|

## 6. 機能性テスト

|ID|テスト項目|前提条件|テスト手順|期待結果|
|---|---|---|---|---|
|6.1|検索機能の動作確認|Sqripts.comのトップページにアクセスする|1. 検索ボックスにキーワード(例:「テスト自動化」)を入力する<br>2. 検索を実行する|入力したキーワードに関連する記事が検索結果に表示される|
|6.2|新規登録機能の確認|「新規登録・ログイン」ページにアクセスする|1. 新規登録に必要な情報を入力する<br>2. 登録ボタンをクリックする|アカウントが正常に作成され、ログイン状態となる|
|6.3|ログイン機能の確認|「新規登録・ログイン」ページにアクセスする|1. 既存アカウントの情報を入力する<br>2. ログインボタンをクリックする|正常にログインでき、ログイン状態となる|

## 7. アクセシビリティテスト

|ID|テスト項目|前提条件|テスト手順|期待結果|
|---|---|---|---|---|
|7.1|画像の代替テキスト確認|ブラウザの開発者ツールを開く|1. トップページの画像要素を検査する<br>2. alt属性の値を確認する|全ての重要な画像に適切な代替テキストが設定されている|
|7.2|キーボードナビゲーション確認|Sqripts.comのトップページにアクセスする|1. マウスを使用せず、Tabキーのみでページ内を移動する<br>2. Enterキーでリンクを開く|キーボードのみでページのすべての機能にアクセスできる|
|7.3|フォントサイズの変更確認|Sqripts.comのトップページにアクセスする|1. ブラウザの設定でフォントサイズを大きくする(Ctrl + または Cmd +)|コンテンツが読みやすく表示され、レイアウトが崩れない|

## 8. セキュリティテスト

|ID|テスト項目|前提条件|テスト手順|期待結果|
|---|---|---|---|---|
|8.1|HTTPSプロトコルの確認|ブラウザでSqripts.comにアクセスする|1. URLバーの鍵アイコンを確認する|サイトがHTTPSで保護されている|
|8.2|パスワード強度の確認|「新規登録・ログイン」ページにアクセスする|1. 新規登録フォームで弱いパスワードを入力する|強度が不足しているパスワードを拒否または警告が表示される|

## 9. クロスブラウザテスト

| ID  | テスト項目        | 前提条件                   | テスト手順                                                                     | 期待結果                   |
| --- | ------------ | ---------------------- | ------------------------------------------------------------------------- | ---------------------- |
| 9.1 | Chrome互換性確認  | Google Chromeブラウザを起動する | 1. Sqripts.comのトップページにアクセスする<br>2. 各セクションの表示を確認する<br>3. リンクをクリックして動作を確認する | すべての機能とデザインが正常に表示・動作する |
| 9.2 | Firefox互換性確認 | Firefoxブラウザを起動する       | 1. Sqripts.comのトップページにアクセスする<br>2. 各セクションの表示を確認する<br>3. リンクをクリックして動作を確認する | すべての機能とデザインが正常に表示・動作する |
| 9.3 | Safari互換性確認  | Safariブラウザを起動する        | 1. Sqripts.comのトップページにアクセスする<br>2. 各セクションの表示を確認する<br>3. リンクをクリックして動作を確認する | すべての機能とデザインが正常に表示・動作する |

このように、AI がテストケースを自動生成してくれました。

今回はあえて簡潔な指示だけで生成してみましたが、より具体的なテストケースが必要な場合は、テスト観点や重要なポイントを詳細に入力することで、それらの指示に沿ったテストケースを生成できます。

要件定義書や基本設計書、詳細設計書などを入力し、適切なプロンプトを与えれば、対象画面と設計書の仕様を照合したテストケースを生成することも可能です。

生成されたテストケースに修正や追加が必要な場合は、具体的な指示を入力するだけで、AI が修正や加筆を行ってくれます。

テストケースを実行してみよう

生成されたテストケースを元に、テストを実行していきます。しかし単純に実行するだけでは、テストの再利用性が確保できません。 そこで、テストを実行しながら、同時にそのテストを再利用可能な形式でアウトプットする方法を検討しました。 今回は、playwright-mcp で実施されているテストを、TypeScript + Playwright コードとして出力することにします。

以下は使用したプロンプトです。

「1.1ヘッダーナビゲーションリンクの動作確認」のテストをplaywrightで操作して実行し、その実行した手順をtypescript + playwrightコードとしてまとめ、最終レポートにテスト結果と、そのテストを再現できるまとめたコードをレポートとして出力してください。

今回の例では、元となるテストケースの抽象度が高く、そのままではテスト実行が困難でしたが、実行過程でより具体的なテストケースが自動生成され、同時にテスト実行も完了してレポートが作成されました。 この結果から、「テストケースを抽象から具象(ステップ)へと変換する」能力が明確に見て取れ、さらに実際の実行までを一貫して行える点が、このテストケース生成システムの大きな強みだと言えます。 もちろん、すべての状況でこれが最適解というわけではなく、ケースによっては適していない場合もあるでしょう。 しかし、このようなテストケース生成システムは、効率的かつ効果的なテスト設計において非常に価値のある強力なツールであることは間違いありません。

作成されたテストコードを実行してみよう

以下が作成されたテストコードです。 このテストコードでは、スクリーンショットを取得していますが、スクリーンショット名にユニーク性がないため、複数のブラウザで実行した場合、後から実行したブラウザのスクリーンショットで上書きされてしまう問題があります。

この問題を解決するため、スクリーンショット名にユニークな値を含めるように修正しました。

また、ファイル名がテストファイルの命名規則に沿っていなかったため、適切な名称に変更しました。

// navigation.spec.ts - Sqripts.comヘッダーナビゲーションリンクのテスト

import { test, expect } from "@playwright/test";

test("1.1 ヘッダーナビゲーションリンクの動作確認", async ({ page }) => {
  // ナビゲーションリンクとその期待されるURLを定義
  const navLinks = [
    { name: "テクノロジー", url: "https://sqripts.com/category/technology/" },
    { name: "品質", url: "https://sqripts.com/category/quality/" },
    {
      name: "エンジニアリング",
      url: "https://sqripts.com/category/engineering/",
    },
    { name: "スクリプター", url: "https://sqripts.com/writer/" },
    { name: "特集", url: "https://sqripts.com/feature/" },
    { name: "ニュース", url: "https://sqripts.com/news/" },
    { name: "資料ダウンロード", url: "/document/" },
    { name: "Sqriptsについて", url: "https://sqripts.com/about/" },
  ];

  // テスト結果を保存する配列
  const results = [];

  // テスト開始時刻を記録
  const startTime = new Date();
  console.log(`テスト開始: ${startTime.toLocaleString()}`);

  try {
    // ホームページに移動
    console.log("Sqripts.comに移動中...");
    await page.goto("https://sqripts.com/");
    await page.waitForLoadState("domcontentloaded");

    console.log("ホームページのスクリーンショットを取得");
    await page.screenshot({ path: "./screenshots/homepage.png" });

    // 各ナビゲーションリンクをテスト
    for (const link of navLinks) {
      try {
        console.log(`ナビゲーションリンクをテスト中: ${link.name}`);

        // ナビゲーションリンクを見つけてクリック
        // ナビゲーションは通常、HTMLではnavタグに含まれているため、このセレクタを使用
        const linkElement = await page
          .locator(`nav >> text="${link.name}"`)
          .first();

        // クリック前にスクロールして要素を表示
        await linkElement.scrollIntoViewIfNeeded();

        // リンク要素がクリック可能かどうかを確認
        await expect(linkElement).toBeVisible();
        await expect(linkElement).toBeEnabled();

        // リンク要素をクリック
        await linkElement.click();

        // ページ遷移の完了を待機
        await page.waitForLoadState("networkidle");

        // 現在のURLを取得
        const currentUrl = page.url();

        // 遷移先ページのスクリーンショットを保存
        await page.screenshot({ path: `./screenshots/${link.name}-page.png` });

        // 期待されるURLに遷移したかどうかを確認
        // 相対URLの場合はベースURLを考慮する
        const expectedUrl = link.url.startsWith("http")
          ? link.url
          : `https://sqripts.com${link.url}`;
        const passed =
          currentUrl === expectedUrl || currentUrl.includes(link.url);

        // テスト結果を保存
        results.push({
          link: link.name,
          expectedUrl: expectedUrl,
          actualUrl: currentUrl,
          passed,
        });

        // コンソールにテスト結果を出力
        if (passed) {
          console.log(`✅ ${currentUrl} に正常に遷移しました`);
        } else {
          console.log(
            `❌ 遷移に失敗しました。期待値: ${expectedUrl}, 実際: ${currentUrl}`
          );
        }

        // 次のテストのためにホームページに戻る
        await page.goto("https://sqripts.com/");
        await page.waitForLoadState("domcontentloaded");
      } catch (error) {
        console.error(`エラー発生 ${link.name}のテスト中: ${error}`);
        results.push({
          link: link.name,
          expectedUrl: link.url,
          actualUrl: "Error",
          passed: false,
          error: error.toString(),
        });
      }
    }
  } catch (error) {
    console.error(`ホームページへの移動に失敗: ${error}`);
  }

  // テスト終了時刻を記録
  const endTime = new Date();
  const testDuration = (endTime.getTime() - startTime.getTime()) / 1000;
  console.log(`テスト終了: ${endTime.toLocaleString()}`);
  console.log(`テスト所要時間: ${testDuration}秒`);

  // テスト結果レポートを生成
  let passCount = 0;
  let failCount = 0;

  console.log("\n========== テスト結果レポート ==========");
  console.log("ヘッダーナビゲーションリンクテスト結果:");
  console.log("===================================");

  for (const result of results) {
    if (result.passed) {
      passCount++;
      console.log(`✅ ${result.link}: 成功`);
      console.log(`   期待値: ${result.expectedUrl}`);
      console.log(`   実際: ${result.actualUrl}`);
    } else {
      failCount++;
      console.log(`❌ ${result.link}: 失敗`);
      console.log(`   期待値: ${result.expectedUrl}`);
      console.log(`   実際: ${result.actualUrl}`);
      if (result.error) {
        console.log(`   エラー: ${result.error}`);
      }
    }
    console.log("-----------------------------------");
  }

  console.log(`\n概要: ${passCount}成功, ${failCount}失敗`);
  console.log("===================================");

  // すべてのナビゲーションリンクが正常に動作したことを検証
  expect(failCount).toBe(0);
});

テストコードを動かすための設定ファイルです。 こちらは自動出力されたものをそのまま使用しています。

この設定は Chromium、Firefox、Webkit の 3 つのブラウザ(エンジン)で実行するように最初から設定されていました。

// playwright.config.ts - Playwrightの設定ファイル

import { PlaywrightTestConfig } from "@playwright/test";

const config: PlaywrightTestConfig = {
  testDir: "./tests",
  timeout: 60000, // タイムアウトを60秒に設定
  reporter: [
    ["html"], // HTMLレポートを生成
    ["list"], // コンソールに結果リストを表示
    ["json", { outputFile: "test-results.json" }], // JSON形式のレポートも生成
  ],
  use: {
    // ブラウザの設定
    headless: false, // テスト実行時にブラウザを表示(視覚的に確認するため)
    viewport: { width: 1280, height: 720 }, // ブラウザのビューポートサイズ
    ignoreHTTPSErrors: true, // HTTPS証明書エラーを無視
    screenshot: "only-on-failure", // 失敗時のみスクリーンショットを撮影
    video: "on-first-retry", // 最初の再試行時にビデオを記録
    trace: "on-first-retry", // 最初の再試行時にトレースを記録

    // アクションのタイムアウト設定
    actionTimeout: 10000, // アクション(クリックなど)のタイムアウトを10秒に設定
    navigationTimeout: 15000, // ナビゲーション(ページ遷移)のタイムアウトを15秒に設定
  },
  // 並列実行の設定
  workers: 1, // シーケンシャルにテストを実行(ナビゲーションテストの場合は順序が重要)
  // プロジェクト固有の設定
  projects: [
    {
      name: "chromium",
      use: { browserName: "chromium" },
    },
    {
      name: "firefox",
      use: { browserName: "firefox" },
    },
    {
      name: "webkit",
      use: { browserName: "webkit" },
    },
  ],
  // フォルダ構造の設定
  outputDir: "test-results/", // テスト結果の出力ディレクトリ
};

export default config;

以下のコマンドを実行してテスト環境を構築しましょう。

macOS の場合

# 新しいディレクトリを作成
mkdir sqripts-test
cd sqripts-test

# npm プロジェクトを初期化
npm init -y

# Playwright をインストール
npm install -D @playwright/test

# Playwright ブラウザをインストール
npx playwright install

# スクリーンショットを保存するディレクトリを作成
mkdir screenshots

mkdir tests
touch tests/navigation.spec.ts
touch playwright.config.ts

Windows の場合

# 新しいディレクトリを作成
mkdir sqripts-test
cd sqripts-test

# npm プロジェクトを初期化
npm init -y

# Playwright をインストール
npm install -D @playwright/test

# Playwright ブラウザをインストール
npx playwright install

# スクリーンショットを保存するディレクトリを作成
mkdir screenshots

# テストディレクトリとファイルを作成
mkdir tests
New-Item -Path tests/navigation.spec.ts -ItemType File
New-Item -Path playwright.config.ts -ItemType File

tests/navigation.spec.ts と playwright.config.ts ファイルに、それぞれ上記のコードを記載しました。

最後にテストを実行してみます。

npx playwright test

ブラウザごとにテストが正常に実行されていることが確認できます。

WebKit はヘッドレスモードで動作しているようです(他のウィンドウの背後に隠れている可能性もあります)が、その他のブラウザは問題なく動作しています。 すべてのブラウザのスクリーンショットは screenshots フォルダに正しく保存されています。

ちなみに今回のテスト動画をよく見ると、Firefox では途中からレイアウトが崩れている箇所があります。 今回のテストケースにはレイアウトのテストが含まれていないため問題なく成功していますが、レイアウトに関するテストケースを作成する場合は、視覚的な検証を行うことでこのような問題を検出できるでしょう。

視覚的な検証を行うには、単純に考えると playwright-mcp サーバーをビジョンモードで動作させる必要があるでしょう。 ただし、今回のテストのように途中でスクリーンショットを撮影している場合は、これらのスクリーンショットを LLM に渡すことでもレイアウトの検証が可能かもしれません。

まとめ

playwright-mcp を使って

  • テストケースを生成
    • テストケースの具象化(ステップ化)
  • テストケースを実行
  • テストケースを再利用可能な形式で出力
    • テストの再実行
  • 結果レポートの生成

これらの機能を活用し、AI を用いたソフトウェアテストを実施しました。 さらに別の技術やMCP、ソフトウェアに関するドキュメントと組み合わせれば

  • テスト結果から仕様書の記載漏れを検出
  • テスト結果と仕様書を突き合わせて想定外の仕様を検出
  • NGテストとGithub MCPを組み合わせて不具合箇所を特定
  • テスト結果に基づく改善点をGithub MCPと連携してリファクタリングを実施

などの様々な活用方法が考えられます。 実際、これらの機能を提供しているプロダクトやサービスはすでに登場しています。

人の手で行わなければならない作業は確実に減少しています。今回紹介した例は単体タスクの依頼であり、自律的なエージェントはまだ登場していません。 しかし、十分な精度を持つ自律型エージェントが登場すれば、人間が行うべき作業は限りなく0に近づいていくでしょう。

1年後にはどのようなソフトウェアテストが可能になっているでしょうか。 1年と言わずとも、わずか1〜2ヶ月で技術が劇的に進化する可能性もあります。

そのような変化が起きた際には、また新たな記事でご紹介したいと思います。 

▼関連記事

#playwright-mcp #Playwright #プレイライト #Cline

SHARE

  • facebook
  • twitter

SQRIPTER

AGEST Engineers

AGEST

記事一覧

AGESTのエンジニアが情報発信してます!
AGESTのサービスやソリューションのお問い合わせページはこちらです。

株式会社AGEST

RANKINGアクセスランキング
#TAGS人気のタグ
  • 新規登録/ログイン
  • 株式会社AGEST
NEWS最新のニュース

Sqriptsはシステム開発における品質(Quality)を中心に、エンジニアが”理解しやすい”Scriptに変換して情報発信するメディアです

  • 新規登録/ログイン
  • 株式会社AGEST