webapp-testing について
Web 開発者向けの Playwright テストスキルで、ブラウザー自動化、エンドツーエンドテスト、複数ブラウザーとモバイル端末のテストを扱います。ネットワークのモック、画面記録、テストの信頼性を高める実践方法も紹介します。
主な機能
- 01複数ブラウザーの自動化
- 02UI 操作とアサーション
- 03ネットワークリクエストのモック
- 04スクリーンショット、動画、トレース
- 05モバイル端末のエミュレーション
- 06テストの信頼性向上の実践
活用シーン
- 01Web のエンドツーエンドテスト作成
- 02エミュレートした端末でのレスポンシブ確認
- 03API をモックしてテスト条件を制御
- 04デバッグ用の視覚的な証跡を記録
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ autumnsgrove/ claudeskills --skill webapp-testingインストール後、Claude Code で/webapp-testingを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
README.mdexamples/api-mocking.mdecommerce-testing.mdform-testing.mdlogin-testing.mdmobile-testing.mdpage-object-model.mdreferences/best-practices.mdci-cd-integration.mdcommon-pitfalls.mdsetup-configuration.mdscripts/playwright_helper.pytest_examples.py詳細
Playwright を使用した Web アプリケーションのテスト
概要
Playwright は、最新のすべてのブラウザー(Chromium、Firefox、WebKit)に対応した、強力な Web テストおよび自動化フレームワークです。自動待機、ネットワーク制御、包括的なテスト機能により、信頼性が高く高速で高機能な自動化を実現します。
次のような場合に、このスキルを使用します。
- Web アプリケーションのエンドツーエンドテストを作成する
- ブラウザーの操作やワークフローを自動化する
- 複数のブラウザーやデバイスでテストする
- UI/UX の機能やアクセシビリティを検証する
- API をモックし、ネットワークリクエストをインターセプトする
- デバッグ用のスクリーンショットや動画を撮影する
主な機能
マルチブラウザーテスト
- Chromium(Chrome、Edge、Brave)
- Firefox(Mozilla Firefox)
- WebKit(Safari エンジン)
- クロスブラウザー互換性テスト
- ブラウザー間での並列実行
要素の操作
- クリック、ダブルクリック、右クリック
- 現実的なキーボードシミュレーションによるテキスト入力
- ドロップダウンやチェックボックスの選択
- ホバーやフォーカスの操作
- ドラッグ&ドロップ操作
- ファイルのアップロードとダウンロード
アサーションと検証
- 要素の表示状態や状態の確認
- テキストコンテンツの検証
- 属性の検証
- URL とナビゲーションのアサーション
- カスタム expect マッチャー
- 複数の確認に対応するソフトアサーション
スクリーンショットと動画の撮影
- ページ全体のスクリーンショット
- 特定の要素の撮影
- テストセッションの動画録画
- ビジュアル比較テスト
- デバッグ用のトレースファイル
ネットワークのインターセプト
- API レスポンスのモック
- リクエストのインターセプトと変更
- ネットワークトラフィックの監視
- オフラインシナリオのテスト
- パフォーマンスの監視
モバイルデバイスのエミュレーション
- 100 種類以上のデバイスプリセット(iPhone、Pixel、iPad など)
- カスタムビューポート設定
- タッチイベントのシミュレーション
- 位置情報のテスト
- 画面の向きの変更
テストの基本的なワークフロー
1. 基本的なテストのセットアップ
Playwright の自動待機を使って、シンプルなテストを作成します。
import pytest
from playwright.sync_api import Page, expect
def test_homepage_loads(page: Page):
"""Test that homepage loads successfully."""
page.goto("https://example.com")
expect(page).to_have_title("Example Domain")
expect(page.locator("h1")).to_contain_text("Example Domain")
def test_navigation(page: Page):
"""Test navigation between pages."""
page.goto("https://example.com")
page.click("text=More information")
expect(page).to_have_url("https://www.iana.org/domains/reserved")
2. フォームの操作
フォームへの入力、検証、送信をテストします。
def test_login_form(page: Page):
"""Test login form submission."""
page.goto("https://example.com/login")
# Fill form fields
page.fill("#username", "[email protected]")
page.fill("#password", "SecurePassword123")
page.check("#remember-me")
# Submit and verify
page.click("button[type='submit']")
expect(page).to_have_url("https://example.com/dashboard")
expect(page.locator(".welcome-message")).to_be_visible()
3. API のモック
制御されたテストを行うため、API レスポンスをモックします。
def test_with_mocked_api(page: Page):
"""Test with mocked API response."""
# Mock API response
page.route("**/api/user", lambda route: route.fulfill(
status=200,
content_type="application/json",
body='{"name": "Test User", "premium": true}'
))
page.goto("https://example.com/profile")
expect(page.locator(".user-name")).to_contain_text("Test User")
4. モバイルエミュレーション
モバイルデバイスでレスポンシブデザインをテストします。
@pytest.fixture
def mobile_page(playwright):
"""Create mobile browser context."""
iphone = playwright.devices['iPhone 12']
browser = playwright.chromium.launch()
context = browser.new_context(**iphone)
page = context.new_page()
yield page
context.close()
browser.close()
def test_mobile_menu(mobile_page: Page):
"""Test mobile navigation."""
mobile_page.goto("https://example.com")
expect(mobile_page.locator(".hamburger-menu")).to_be_visible()
mobile_page.click(".hamburger-menu")
expect(mobile_page.locator(".mobile-menu")).to_be_visible()
5. ビジュアルリグレッション
ビジュアル比較用にスクリーンショットを撮影します。
def test_homepage_screenshot(page: Page):
"""Capture homepage screenshot."""
page.goto("https://example.com")
# Full page screenshot
page.screenshot(path="screenshots/homepage.png", full_page=True)
# Element screenshot
page.locator("header").screenshot(path="screenshots/header.png")
# Screenshot with masks for dynamic content
page.screenshot(
path="screenshots/dashboard.png",
mask=[page.locator(".timestamp"), page.locator(".session-id")]
)
テストの主な原則
信頼性の高いセレクターを使用する
# ✅ GOOD: Test IDs and semantic selectors
page.click("[data-testid='submit-button']")
page.click("button:text('Submit')")
page.click("role=button[name='Submit']")
# ❌ BAD: Fragile structural selectors
page.click("div > div > button:nth-child(3)")
自動待機を活用する
# ✅ GOOD: Playwright auto-waits
page.click("button")
expect(page.locator(".result")).to_be_visible()
# ⚠️ Avoid: Manual waits
time.sleep(2) # Only when absolutely necessary
テストを分離する
# ✅ GOOD: Clean state between tests
@pytest.fixture(autouse=True)
def clear_state(page: Page):
yield
page.context.clear_cookies()
page.evaluate("localStorage.clear()")
不安定なテストに対処する
# ✅ GOOD: Wait for specific conditions
page.click("button")
page.wait_for_selector(".result")
result = page.locator(".result").text_content()
# ✅ GOOD: Use soft assertions
expect.soft(page.locator(".title")).to_be_visible()
expect.soft(page.locator(".price")).to_contain_text("$")
ページオブジェクトモデル
保守性を高めるため、ページオブジェクトパターンを使用してテストを整理します。
class LoginPage:
"""Login page object."""
def __init__(self, page: Page):
self.page = page
self.username_input = page.locator("#username")
self.password_input = page.locator("#password")
self.submit_button = page.locator("button[type='submit']")
def login(self, username: str, password: str):
"""Perform login."""
self.username_input.fill(username)
self.password_input.fill(password)
self.submit_button.click()
# Use in tests
def test_login(page: Page):
login_page = LoginPage(page)
login_page.login("[email protected]", "password123")
expect(page).to_have_url("/dashboard")
一般的なテストパターン
認証
@pytest.fixture
def authenticated_page(page: Page):
"""Provide authenticated session."""
page.goto("https://example.com/login")
page.fill("#username", "[email protected]")
page.fill("#password", "password")
page.click("button[type='submit']")
page.wait_for_url("**/dashboard")
yield page
ファイル操作
# Upload
page.set_input_files("#file-input", "path/to/file.pdf")
# Download
with page.expect_download() as download_info:
page.click("a:text('Download')")
download = download_info.value
download.save_as("downloads/file.pdf")
ネットワーク監視
requests = []
page.on("request", lambda req: requests.append(req))
page.goto("https://example.com")
# Verify API calls were made
api_requests = [r for r in requests if "/api/" in r.url]
assert len(api_requests) > 0
テストの実行
基本的なコマンド
# Install Playwright
pip install playwright pytest-playwright
playwright install
# Run all tests
pytest tests/
# Run specific browser
pytest --browser chromium --browser firefox
# Run in headed mode (see browser)
pytest --headed
# Debug mode
PWDEBUG=1 pytest tests/test_login.py
# Parallel execution
pytest -n auto
# Generate test code
playwright codegen https://example.com
設定
references/setup-configuration.md を参照してください。
- インストール手順の全容
- プロジェクト構造のセットアップ
- pytest.ini の設定
- TypeScript 用の playwright.config.ts
- CI/CD 統合の例
品質基準
テストが次の基準を満たしていることを確認してください。
- テストが互いに独立しており、任意の順序で実行できる
- セレクターの信頼性が高い(テスト ID、セマンティックセレクター)
- 適切なエラー処理とアサーションがある
- 失敗時にスクリーンショットや動画が撮影される
- 固定時間の待機を使用しない(自動待機を使用する)
- テスト間で状態が適切に管理されている
追加リソース
詳細なドキュメント
- セットアップと設定 - インストール、プロジェクト構造、設定
- ベストプラクティス - セレクター戦略、待機パターン、不安定なテストの防止
- よくある落とし穴 - 競合状態、脆弱なセレクター、クリーンアップの問題
- CI/CD 統合 - GitHub Actions、Docker、デプロイパイプライン
コード例
- ログインテスト - 認証フローとセッション管理
- フォームテスト - フォームの検証、ファイルのアップロード、ドロップダウン
- Eコマーステスト - ショッピングカート、チェックアウトフロー、クーポン
- APIモック - ネットワークの傍受、モック、監視
- モバイルテスト - デバイスのエミュレーション、タッチイベント、レスポンシブデザイン
- ページオブジェクトモデル - POMパターンの実装
ヘルパースクリプト
- Playwrightヘルパー - Playwrightの一般的な操作に使用するユーティリティ関数
- テスト例 - テストスイートの完全な例
外部リソース
- 公式ドキュメント: https://playwright.dev
- Python API: https://playwright.dev/python/docs/intro
- TypeScript API: https://playwright.dev/docs/intro
- ベストプラクティス: https://playwright.dev/docs/best-practices
- コミュニティDiscord: https://aka.ms/playwright/discord
トラブルシューティング
テストが不安定です:
- 手動で待機する代わりに、Playwrightの自動待機を使用します
- 適切な待機条件(
wait_for_selector、wait_for_url)を設定します - 自動再試行される
expect()アサーションを使用します
セレクターで要素が見つかりません:
- ブラウザーのDevToolsで要素が存在することを確認します
- Playwright Inspectorを使用します:
PWDEBUG=1 pytest test.py - 複数のセレクター戦略(テキスト、ロール、テストID)を試します
CIでテストが遅いです:
- 並列実行を有効にします:
pytest -n auto - デバッグ時のみヘッド付きモードを使用します
- 関連するテストでブラウザーコンテキストの再利用を検討します
トラブルシューティングのヒントについては、よくある落とし穴を参照してください。
コメント
Markdown 対応