Yapodu Tech Blog

株式会社ヤポドゥの技術ブログです。

【テスト, 監視シナリオ編】Playwright MCP を WSL2 経由で実行する

前回の続きです。
Playwright MCP で WSL2 Docker の Playwright が起動できることを確認したので、以下を評価、作成していきます。

  • Web サイトのテストケース
  • 監視用のログイン - ログアウトのシナリオ

Playwright MCP でのテストケース

前提

  • テストサイトはEC サイトのデモ用として使用可能な www.saucedemo.com で実行する
  • Markdown での簡易的なテストケースが存在している。
  • 指示は 前回動作確認をした Docker 環境 で行う。

www.saucedemo.com

www.saucedemo.com

Cline への指示

既存のテストケースを Playwright で実行可能なコードとして出力し、その後ブラウザ操作を行い、テストケースの追加を行うよう指示をします。

- 日本語で回答してください。
- Playwright MCP を使用してください。
    - Playwright MCP は http://localhost:9876/sse で起動済みです。
- 以下のサイトのテストケースを作成しました。
    - テストを行う URL: https://www.saucedemo.com/
    - 前提: システムの構築が完了したので、テストを実行する準備が整いました。
    - テストケース    

TC‐ID | タイトル | 目的/カバー範囲 | 前提条件 | 手順 | 期待結果
TC‑01 | 標準ユーザーで正常ログイン | 認証処理とダッシュボード表示を確認 | standard_user / secret_sauce の資格情報が有効<200b>saucedemo.com | 1. https://www.saucedemo.com/ にアクセス2. ユーザー名欄に standard_user を入力3. パスワード欄に secret_sauce を入力4. LOGIN ボタンをクリック | ① /inventory.html に遷移する② ページタイトル「Products」が表示される
TC‑02 | ログイン失敗(ロックアウトユーザー) | エラーメッセージ表示を確認 | なし | 1‑4. TC‑01 と同様だがユーザー名は locked_out_user | フォーム下に赤字のエラーバナー「Sorry, this user has been locked out.」が表示される
TC‑03 | 商品を 1 点カートに追加 | 追加ボタン動作とカートバッジ更新 | ログイン済み(TC‑01 成功後) | 1. 最初のアイテム Add to cart をクリック2. 右上カートアイコンを確認 | ① ボタンが Remove に変わる② カートバッジの数が「1」になる
TC‑04 | カートから商品を削除 | Remove ボタンとバッジ更新を確認 | TC‑03 の続き | 1. カートアイコンをクリック→/cart.html2. Remove をクリック | ① 商品行が一覧から消える② カートバッジが消える/「0」になる
TC‑05 | 並べ替え機能(価格:低→高) | ドロップダウンソートが正しく機能するか | ログイン済み | 1. /inventory.html で右上 Sort ドロップダウンを Price (low to high) に変更 | 商品カードが「$7.99 → … → $49.99」の昇順で並ぶ
TC‑06 | 購入フロー完走 | Checkout 手順と合計計算 | カートに 2 品追加済み | 1. /cart.html → Checkout2. フォームに First/Last/Zip を入力3. Continue → 確認画面で内容確認4. Finish | ① /checkout-complete.html へ遷移② “THANK YOU FOR YOUR ORDER” が表示される  

- このテストケースに不足があれば、追加してください。
- テストケースの内容を Playwright で実行できるように、コードを作成してください。

実行

テキストベースのケースに沿ってテストケースコードが作成されます、 対応するケース No も記載されていることが確認できます。

※コード作成時に追加の Playwright MCPのツールの導入を求められるので、すべて許可を与えてます。

// @ts-check
const { test, expect } = require('@playwright/test');

/**
 * SauceDemo Webサイトのテストスイート
 * テストケースID: TC-01~TC-06
 */

test.describe('SauceDemo テストスイート', () => {
  // 各テスト前に実行
  test.beforeEach(async ({ page }) => {
    // ベースURLに移動
    await page.goto('https://www.saucedemo.com/');
  });

  /**
   * TC-01: 標準ユーザーで正常ログイン
   * 目的: 認証処理とダッシュボード表示を確認
   */
  test('TC-01: 標準ユーザーで正常ログイン', async ({ page }) => {
    // 1. ユーザー名欄に standard_user を入力
    await page.fill('[data-test="username"]', 'standard_user');
    
    // 2. パスワード欄に secret_sauce を入力
    await page.fill('[data-test="password"]', 'secret_sauce');
    
    // 3. LOGIN ボタンをクリック
    await page.click('[data-test="login-button"]');
    
    // 期待結果①: /inventory.html に遷移する
    await expect(page).toHaveURL(/.*\/inventory.html/);
    
    // 期待結果②: ページタイトル「Products」が表示される
    await expect(page.locator('.title')).toHaveText('Products');
  });

コードの作成が完了すると WSL2 上でブラウザが実行されサイトの確認を行い追加のテストケース作成を行います。

最後に以下の項目が含まれている README.md がテストコード配置ディレクトリに追加されました。

  • 概要
  • テストケース一覧
  • テストの実行方法
  • ファイル構成

実行結果

  • 既存のテキストテストケースにに対応するテストコードがリポジトリディレクトリに沿って配置される
  • テストケースが4つ追加
  • README.md がテストディレクトリに新規作成される
  • API 費用: 約 $0.73

指示として、もっと具体的に実行したいケースや、技術を提示すれば、ケースはさらに増えていきますので是非お試しください。

Playwright MCP での監視用シナリオ

続いては、監視シナリオを作成します。

前提

  • テストケースの作業情報とファイルは一旦消去して実施
  • 言語として Python 3.12 を指定
  • 想定実行環境は Docker コンテナでの実行

Cline への指示

情報としてECサイトのログイン - ログアウトの監視用シナリオを python で作成したいことを伝えます。
当初はもう少しシンプルな指示で作成を試みてましたが、どうも Sonnet さんが、作業リポジトリの Docker 周辺をどうしても操作したがるので、若干長めになりました。

- 日本語で回答してください。
- Playwright MCP を使用して [調査] ください。
    - Playwright MCP は http://localhost:9876/sse で起動済みです。
    - 必要であれば、ブラウザを起動しサイトを操作して調査してください。
- Playwright ログイン - ログアウト用監視シナリオを作成してください。
    - テストを行う URL: https://www.saucedemo.com/
    - 前提: システムの構築が完了したので、テストを実行する準備が整いました。
    - 言語は Playwright for Python の 3.12 で作成してください。
    - Python のシナリオを実行する際は Playwright MCP は使用しない前提で作成してください。
    - 動作環境はこのリポジトリではなく Docker 上で汎用的に動作するように作成してください。
    - 動作可能な手順を新規の README.md に記載してください。

実行

指示通りにブラウザが起動され、ログイン - ログアウトの動作を確認がされました。 その後に新規にテストコード実行用ディレクトリが作成され、Dockerfiledocker-compose.yml が作成され、 シナリオ用 py ファイルも作成されてます。 README.md は新規作成ではなく既存への追記となってますが、こちらも指示次第で修正は可能です。

$ tree .
.
├── Dockerfile
├── README.md
├── cline_mcp_settings.json.example
├── docker-compose.yml
├── login_logout_test.py
├── scenario
│   └── entrypoint.sh
└── test
    ├── Dockerfile
    └── docker-compose.yml

テストコードも headless で記載されています。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
Sauce Demo サイトのログイン・ログアウトテストシナリオ
"""

import asyncio
from playwright.async_api import async_playwright


async def run_login_logout_test():
    """
    Sauce Demo サイトのログイン・ログアウトテストを実行する
    """
    async with async_playwright() as playwright:
        # 環境変数からヘッドレスモードの設定を取得(デフォルトはTrue)
        import os
        headless = os.environ.get('HEADLESS', 'True').lower() in ('true', '1', 't')
        print(f"ヘッドレスモード: {headless}")
        
        # ブラウザを起動
        browser = await playwright.chromium.launch(headless=headless)
        context = await browser.new_context()
        page = await context.new_page()

        # テスト開始のログを出力
        print("テスト開始: Sauce Demo ログイン・ログアウトテスト")

        try:
            # ログインページにアクセス
            await page.goto("https://www.saucedemo.com/")
            print("ページにアクセスしました: https://www.saucedemo.com/")

            # ページタイトルを確認
            title = await page.title()
            assert title == "Swag Labs", f"ページタイトルが一致しません。期待値: 'Swag Labs', 実際: '{title}'"
            print(f"ページタイトル確認: {title}")

            # ユーザー名とパスワードを入力
            await page.fill('input[data-test="username"]', "standard_user")
            await page.fill('input[data-test="password"]', "secret_sauce")
            print("ユーザー名とパスワードを入力しました")

            # ログインボタンをクリック
            await page.click('input[data-test="login-button"]')
            print("ログインボタンをクリックしました")

            # 商品ページに遷移したことを確認
            await page.wait_for_url("https://www.saucedemo.com/inventory.html")
            inventory_title = await page.title()
            assert inventory_title == "Swag Labs", "ログイン後のページタイトルが一致しません"
            
            # 商品ページのヘッダーテキストを確認
            products_header = await page.text_content(".title")
            assert products_header == "Products", f"商品ページのヘッダーが一致しません。期待値: 'Products', 実際: '{products_header}'"
            print("ログインに成功し、商品ページに遷移しました")

            # メニューボタンをクリック
            await page.click('#react-burger-menu-btn')
            print("メニューボタンをクリックしました")

            # ログアウトリンクが表示されるまで待機
            await page.wait_for_selector('#logout_sidebar_link', state="visible")
            
            # ログアウトリンクをクリック
            await page.click('#logout_sidebar_link')
            print("ログアウトリンクをクリックしました")

            # ログインページに戻ったことを確認
            await page.wait_for_url("https://www.saucedemo.com/")
            login_title = await page.title()
            assert login_title == "Swag Labs", "ログアウト後のページタイトルが一致しません"
            
            # ログインボタンが表示されていることを確認
            login_button = await page.is_visible('input[data-test="login-button"]')
            assert login_button, "ログインボタンが表示されていません"
            print("ログアウトに成功し、ログインページに戻りました")

            print("テスト成功: ログイン・ログアウトのフローが正常に完了しました")
            
        except Exception as e:
            print(f"テスト失敗: {str(e)}")
            raise
        finally:
            # ブラウザを閉じる
            await browser.close()
            print("テスト終了: ブラウザを閉じました")


if __name__ == "__main__":
    asyncio.run(run_login_logout_test())

実行結果

  • テスト用 Docker 環境作成
  • Python のテストコードが作成
  • 既存の README.md へ追記される
  • API 費用: 約 $0.27

最後に

2 回にわたって Playwright MCP を操作し、テストケース生成と監視シナリオ構築の両方を確認できました。
テストケース × 監視シナリオ を組み合わせれば、これまで手動で行っていた運用テストもコード化して自動化できます。
CI/CD への組み込みや継続的監視に応用し、開発スピードと品質向上にぜひ役立ててみてください。

参考