qa-team について
qa-teamは、ユーザーから見える操作を通じてアプリの振る舞いを検証する、宣言型の外部視点テスト向けスキルです。gadugi-agentic-testを使い、CLI、TUI、Web、Electronのシナリオに加え、実装比較やリリース時の差異記録にも対応します。
主な機能
- 01YAMLによる振る舞いシナリオ
- 02CLI、TUI、Web、Electronのテスト
- 03エージェントによる操作と結果検証
- 04証跡の収集とレポート生成
- 05実装比較とシャドーモード
活用シーン
- 01変更後に重要なユーザーフローを確認
- 02アプリ種別をまたいだ振る舞いのテスト
- 03旧実装と置き換え実装の比較
- 04実行を止めずにリリース差異を記録
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ rysweet/ amplihack --skill qa-teamインストール後、Claude Code で/qa-teamを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
README.mdexamples/cli/calculator-basic.yamlcli-error-handling.yamlcli-interactive-session.yamlexamples/custom-agents/custom-comprehension-agent.yamlcustom-reporter-integration.yamlexamples/electron/electron-ipc-testing.yamlelectron-menu-testing.yamlmulti-window-coordination.yamlsingle-window-basic.yamlexamples/tui/file-manager-navigation.yamltui-form-validation.yamltui-performance-monitoring.yamlexamples/web/dashboard-smoke-test.yamlweb-authentication-flow.yamlweb-visual-regression.yamlscripts/check-freshness.pytests/test_skill_examples.py詳細
QA チームスキル
目的 [LEVEL 1]
このスキルは、内部実装について何も知らなくても、外部ユーザーの視点からアプリケーションの動作を検証するエージェント型の外部視点テストの作成に役立ちます。gadugi-agentic-test フレームワークを使用し、AI エージェントが実行、観察、検証する宣言型の YAML シナリオを作成します。
重要な原則:テストでは、どのように実装されているかではなく、何が起きるべきかを記述します。実行の詳細はエージェントが判断します。
このスキルを使う場面 [LEVEL 1]
最適な用途
- スモークテスト:重要なユーザーフローが機能することをすばやく検証します
- 振る舞い駆動テスト:ユーザーの視点から機能を検証します
- クロスプラットフォームテスト:CLI、TUI、Web、Electron で同じテストロジックを使用します
- リファクタリング時の安全性確保:実装が変更されてもテストの有効性を維持します
- AI を活用したテスト:複雑な操作をエージェントに任せます
- テストとしてのドキュメント:YAML シナリオを実行可能な仕様としても活用します
次のような場合にこのスキルを使います
- 新しいプロジェクトを開始し、期待される動作を定義するとき
- コードをリファクタリングする際、内部変更で壊れないテストが必要なとき
- ユーザー向けアプリケーション(CLI ツール、TUI、Web アプリ、デスクトップアプリ)をテストするとき
- 自動検証可能な受け入れ基準を作成するとき
- 開発者以外も読んで理解できるテストが必要なとき
- 重要なユーザーワークフローのリグレッションを検出したいとき
- 複雑な複数ステップの操作をテストするとき
次のような場合はこのスキルを使わないでください
- 内部関数の単体テストが必要な場合(代わりに test-gap-analyzer を使います)
- パフォーマンスや負荷特性をテストする場合
- 厳密なタイミング制御や並行処理制御が必要な場合
- 対話型ではないバッチ処理をテストする場合
- 動作よりも実装の詳細が重要な場合
基本概念 [LEVEL 1]
外部視点テストの考え方
従来の内部起点テスト:
# Tightly coupled to implementation
def test_calculator_add():
calc = Calculator()
result = calc.add(2, 3)
assert result == 5
assert calc.history == [(2, 3, 5)] # Knows internal state
エージェント型の外部視点テスト:
# Implementation-agnostic behavior verification
scenario:
name: "Calculator Addition"
steps:
- action: launch
target: "./calculator"
- action: send_input
value: "add 2 3"
- action: verify_output
contains: "Result: 5"
メリット:
- リファクタリング後もテストを維持できます(内部変更でテストが壊れません)
- 開発者以外も読みやすい形式です(YAML は宣言型です)
- プラットフォームに依存しません(CLI/TUI/Web/Electron で同じ構造を使えます)
- AI エージェントが複雑な処理(画面移動、タイミング調整、スクリーンショット)を担います
Gadugi Agentic Test フレームワーク [LEVEL 2]
Gadugi-agentic-test は、次の処理を行う Python フレームワークです。
- 宣言型ステップを含む YAML テストシナリオを解析する
- 専用エージェントに処理を振り分ける(CLI、TUI、Web、Electron エージェント)
- アクションを実行する(起動、入力、クリック、待機、検証)
- 証拠を収集する(スクリーンショット、ログ、出力の取得)
- 期待される結果と照らし合わせて結果を検証する
- 証拠の追跡情報を含むレポートを生成する
アーキテクチャ:
YAML Scenario → Scenario Loader → Agent Dispatcher → Execution Engine
↓
[CLI Agent, TUI Agent, Web Agent, Electron Agent]
↓
Observers → Comprehension Agent
↓
Evidence Report
段階的開示のレベル [LEVEL 1]
このスキルでは、4 つのレベルに分けてテスト方法を説明します。
- レベル 1:基礎 - 単一アクションの基本的なテスト、簡単な検証
- レベル 2:中級 - 複数ステップのフロー、条件分岐、エラー処理
- レベル 3:上級 - カスタムエージェント、ビジュアルリグレッション、パフォーマンス検証
- レベル 4:パリティとシャドーイング - 並列での A/B 比較、リモートでの観測可能な実行、ロールアウト時の差異の記録
各例にはレベルが示されています。レベル 1 から始め、必要に応じて先へ進んでください。
並列パリティと A/B 検証 [LEVEL 2]
QA Team は、以前 outside-in-testing と呼ばれていた主要スキルの名称を変更したものです。標準的な外部視点シナリオに加えて、外部ユーザーから見える動作を基準に、レガシー実装と置き換え後の実装、またはアプローチ A とアプローチ B を比較する必要があるパリティ検証のループにも使用できます。
次のようなパリティ作業には QA Team を使います
- Python から Rust への移行、旧 CLI から新 CLI への移行、または v1 から v2 への動作変更を行う場合
- デフォルトを切り替える前にリライトを検証する場合
- 同じユーザーシナリオを使ってブランチ A とブランチ B を比較する場合
- ペアになった仮想 TTY で、並列セッションを観測しながら実行する場合
- 実行を失敗させずに、シャドーモードでロールアウト時の差異を記録する場合
推奨するパリティループ
- まず、共通のユーザー向けシナリオを定義します。
- 両方の実装を分離されたサンドボックスで実行します。
- 標準出力、標準エラー、終了コード、JSON 出力、ファイルシステムへの副作用を比較します。
- デバッグ用に対応する tmux ペインが必要な場合は、
--observableモードで再実行します。 azlinなどのリモート環境でパリティを実現する必要がある場合は、--ssh-target <host>を使用します。- ロールアウト中に実行をブロックせず差異をログに記録するには、
--shadow-mode --shadow-log <file>を使用します。
再利用するコマンドパターン
リポジトリにすでにパリティハーネスがある場合は、2つ目のものを新たに作成せず、既存のものを拡張します。基本形は次のとおりです。
python tests/parity/validate_cli_parity.py \
--scenario tests/parity/scenarios/feature.yaml \
--python-repo /path/to/legacy-repo \
--rust-binary /path/to/new-binary \
--observable
リモートでのパリティの場合:
python tests/parity/validate_cli_parity.py \
--ssh-target azlin \
--scenario tests/parity/scenarios/feature.yaml \
--python-repo /remote/path/to/legacy-repo \
--rust-binary /remote/path/to/new-binary
ロールアウト時のシャドウログ記録の場合:
python tests/parity/validate_cli_parity.py \
--scenario tests/parity/scenarios/feature.yaml \
--python-repo /path/to/legacy-repo \
--rust-binary /path/to/new-binary \
--shadow-mode \
--shadow-log /tmp/feature-shadow.jsonl
クイックスタート [LEVEL 1]
インストール
前提条件(ネイティブモジュールのコンパイル用):
# macOS
xcode-select --install
# Ubuntu/Debian
sudo apt-get install -y build-essential python3
# Windows: Install Visual Studio Build Tools with "Desktop development with C++"
フレームワークをインストールします:
# Install globally for CLI access
npm install -g @gadugi/agentic-test
# Or install locally in your project
npm install @gadugi/agentic-test
# Verify installation
gadugi-test --version
最初のテスト(CLI の例)
test-hello.yaml を作成します:
scenario:
name: "Hello World CLI Test"
description: "Verify CLI prints greeting"
type: cli
prerequisites:
- "./hello-world executable exists"
steps:
- action: launch
target: "./hello-world"
- action: verify_output
contains: "Hello, World!"
- action: verify_exit_code
expected: 0
テストを実行します:
gadugi-test run test-hello.yaml
出力:
✓ Scenario: Hello World CLI Test
✓ Step 1: Launched ./hello-world
✓ Step 2: Output contains "Hello, World!"
✓ Step 3: Exit code is 0
PASSED (3/3 steps successful)
Evidence saved to: ./evidence/test-hello-20250116-093045/
YAML 構造を理解する [LEVEL 1]
各テストシナリオは次の構造です:
scenario:
name: "Descriptive test name"
description: "What this test verifies"
type: cli | tui | web | electron
# Optional metadata
tags: [smoke, critical, auth]
timeout: 30s
# What must be true before test runs
prerequisites:
- "Condition 1"
- "Condition 2"
# The test steps (executed sequentially)
steps:
- action: action_name
parameter1: value1
parameter2: value2
- action: verify_something
expected: value
# Optional cleanup
cleanup:
- action: stop_application
アプリケーションの種類とエージェント [LEVEL 2]
CLI アプリケーション [LEVEL 1]
用途:コマンドラインツール、スクリプト、ビルドツール、パッケージマネージャー
サポートされるアクション:
launch- CLI プログラムを起動しますsend_input- stdin 経由でテキストまたはコマンドを送信しますsend_signal- OS シグナル(SIGINT、SIGTERM)を送信しますwait_for_output- 標準出力/標準エラーで特定のテキストが出力されるまで待機しますverify_output- 標準出力/標準エラーに想定されるテキストが含まれているか、一致するかを確認しますverify_exit_code- プロセスの終了コードを検証しますcapture_output- 後で検証するために出力を保存します
例(examples/cli/calculator-basic.yaml を参照):
scenario:
name: "CLI Calculator Basic Operations"
type: cli
steps:
- action: launch
target: "./calculator"
args: ["--mode", "interactive"]
- action: send_input
value: "add 5 3\n"
- action: verify_output
contains: "Result: 8"
timeout: 2s
- action: send_input
value: "multiply 4 7\n"
- action: verify_output
contains: "Result: 28"
- action: send_input
value: "exit\n"
- action: verify_exit_code
expected: 0
TUI アプリケーション [LEVEL 1]
用途:ターミナルユーザーインターフェース(htop、vim、tmux、カスタムダッシュボード TUI)
サポートされるアクション:
launch- TUI アプリケーションを起動しますsend_keypress- キーボード入力(矢印キー、Enter、ctrl+c など)を送信しますwait_for_screen- 画面に特定のテキストが表示されるまで待機しますverify_screen- 画面の内容が想定どおりかを確認しますcapture_screenshot- ターミナルのスクリーンショット(ANSI アート)を保存しますnavigate_menu- メニュー構造を操作しますfill_form- TUI のフォームフィールドに入力します
例(examples/tui/file-manager-navigation.yaml を参照):
scenario:
name: "TUI File Manager Navigation"
type: tui
steps:
- action: launch
target: "./file-manager"
- action: wait_for_screen
contains: "File Manager v1.0"
timeout: 3s
- action: send_keypress
value: "down"
times: 3
- action: verify_screen
contains: "> documents/"
description: "Third item should be selected"
- action: send_keypress
value: "enter"
- action: wait_for_screen
contains: "documents/"
timeout: 2s
- action: capture_screenshot
save_as: "documents-view.txt"
Web アプリケーション [LEVEL 1]
用途:Web アプリ、ダッシュボード、SPA、管理パネル
サポートされるアクション:
navigate- URL に移動しますclick- セレクターまたはテキストで要素をクリックしますtype- 入力フィールドにテキストを入力しますwait_for_element- 要素が表示されるまで待機しますverify_element- 要素の存在や、テキストが含まれているかを確認しますverify_url- 現在の URL を検証しますscreenshot- ブラウザーのスクリーンショットを撮影しますscroll- ページまたは要素をスクロールします
例(examples/web/dashboard-smoke-test.yaml を参照):
scenario:
name: "Dashboard Smoke Test"
type: web
steps:
- action: navigate
url: "http://localhost:3000/dashboard"
- action: wait_for_element
selector: "h1.dashboard-title"
timeout: 5s
- action: verify_element
selector: "h1.dashboard-title"
contains: "Analytics Dashboard"
- action: verify_element
selector: ".widget-stats"
count: 4
description: "Should have 4 stat widgets"
- action: click
selector: "button.refresh-data"
- action: wait_for_element
selector: ".loading-spinner"
disappears: true
timeout: 10s
- action: screenshot
save_as: "dashboard-loaded.png"
Electron アプリケーション [LEVEL 2]
用途:Electron で構築されたデスクトップアプリ(VS Code、Slack、Discord のクローン)
サポートされるアクション:
launch- Electron アプリを起動しますwindow_action- ウィンドウを操作します(フォーカス、最小化、閉じる)menu_click- アプリケーションのメニュー項目をクリックしますdialog_action- ネイティブダイアログを処理します(ファイルを開く、保存、確認)ipc_send- メインプロセスに IPC メッセージを送信しますverify_window- ウィンドウの状態/プロパティを確認します- すべての Web アクション(Electron は Chromium を使用するため)
例(examples/electron/single-window-basic.yaml を参照):
scenario:
name: "Electron Single Window Test"
type: electron
steps:
- action: launch
target: "./dist/my-app"
wait_for_window: true
timeout: 10s
- action: verify_window
title: "My Application"
visible: true
- action: menu_click
path: ["File", "New Document"]
- action: wait_for_element
selector: ".document-editor"
- action: type
selector: ".document-editor"
value: "Hello from test"
- action: menu_click
path: ["File", "Save"]
- action: dialog_action
type: save_file
filename: "test-document.txt"
- action: verify_window
title_contains: "test-document.txt"
テストシナリオの構成 [LEVEL 2]
メタデータセクション
scenario:
name: "Clear descriptive name"
description: "Detailed explanation of what this test verifies"
type: cli | tui | web | electron
# Optional fields
tags: [smoke, regression, auth, payment]
priority: high | medium | low
timeout: 60s # Overall scenario timeout
retry_on_failure: 2 # Retry count
# Environment requirements
environment:
variables:
API_URL: "http://localhost:8080"
DEBUG: "true"
files:
- "./config.json must exist"
前提条件
前提条件とは、テストの実行前に満たされていなければならない条件です。フレームワークは実行前にこれらを検証します。
prerequisites:
- "./application binary exists"
- "Port 8080 is available"
- "Database is running"
- "User account [email protected] exists"
- "File ./test-data.json exists"
前提条件を満たさない場合、テストは失敗ではなくスキップされます。
ステップ
ステップは順番に実行されます。各ステップには次の項目があります:
- action:必須 - 実行するアクション
- Parameters:アクション固有のパラメーター
- description:任意 - 人が読める説明
- timeout:任意 - ステップ固有のタイムアウト
- continue_on_failure:任意 - ステップが失敗してもシナリオ全体を失敗にしません
steps:
# Simple action
- action: launch
target: "./app"
# Action with multiple parameters
- action: verify_output
contains: "Success"
timeout: 5s
description: "App should print success message"
# Continue even if this fails
- action: click
selector: ".optional-button"
continue_on_failure: true
検証アクション [LEVEL 1]
検証アクションは期待される結果を確認します。期待が満たされない場合、テストは失敗します。
一般的な検証:
# CLI: Check output contains text
- action: verify_output
contains: "Expected text"
# CLI: Check output matches regex
- action: verify_output
matches: "Result: \\d+"
# CLI: Check exit code
- action: verify_exit_code
expected: 0
# Web/TUI: Check element exists
- action: verify_element
selector: ".success-message"
# Web/TUI: Check element contains text
- action: verify_element
selector: "h1"
contains: "Welcome"
# Web: Check URL
- action: verify_url
equals: "http://localhost:3000/dashboard"
# Web: Check element count
- action: verify_element
selector: ".list-item"
count: 5
# Electron: Check window state
- action: verify_window
title: "My App"
visible: true
focused: true
クリーンアップセクション
クリーンアップは、すべてのステップの完了後(成功・失敗を問わず)に実行されます。後処理アクションに使用します。
cleanup:
- action: stop_application
force: true
- action: delete_file
path: "./temp-test-data.json"
- action: reset_database
connection: "test_db"
高度なパターン [LEVEL 2]
条件分岐
条件に基づいてステップを実行します:
steps:
- action: launch
target: "./app"
- action: verify_output
contains: "Login required"
id: login_check
# Only run if login_check passed
- action: send_input
value: "login admin password123\n"
condition: login_check.passed
変数とテンプレート [LEVEL 2]
変数を定義し、シナリオ全体で使用します:
scenario:
name: "Test with Variables"
type: cli
variables:
username: "testuser"
api_url: "http://localhost:8080"
steps:
- action: launch
target: "./app"
args: ["--api", "${api_url}"]
- action: send_input
value: "login ${username}\n"
- action: verify_output
contains: "Welcome, ${username}!"
ループと繰り返し [LEVEL 2]
アクションを複数回繰り返します:
steps:
- action: launch
target: "./app"
# Repeat action N times
- action: send_keypress
value: "down"
times: 5
# Loop over list
- action: send_input
value: "${item}\n"
for_each:
- "apple"
- "banana"
- "cherry"
エラー処理 [LEVEL 2]
想定されるエラーを適切に処理します:
steps:
- action: send_input
value: "invalid command\n"
# Verify error message appears
- action: verify_output
contains: "Error: Unknown command"
expected_failure: true
# App should still be running
- action: verify_running
expected: true
マルチステップのワークフロー [LEVEL 2]
複数のフェーズから成る複雑なシナリオです:
scenario:
name: "E-commerce Purchase Flow"
type: web
steps:
# Phase 1: Authentication
- action: navigate
url: "http://localhost:3000/login"
- action: type
selector: "#username"
value: "[email protected]"
- action: type
selector: "#password"
value: "password123"
- action: click
selector: "button[type=submit]"
- action: wait_for_url
contains: "/dashboard"
# Phase 2: Product Selection
- action: navigate
url: "http://localhost:3000/products"
- action: click
text: "Add to Cart"
nth: 1
- action: verify_element
selector: ".cart-badge"
contains: "1"
# Phase 3: Checkout
- action: click
selector: ".cart-icon"
- action: click
text: "Proceed to Checkout"
- action: fill_form
fields:
"#shipping-address": "123 Test St"
"#city": "Testville"
"#zip": "12345"
- action: click
selector: "#place-order"
- action: wait_for_element
selector: ".order-confirmation"
timeout: 10s
- action: verify_element
selector: ".order-number"
exists: true
レベル 3:高度なトピック [LEVEL 3]
カスタム解釈エージェント
このフレームワークは AI エージェントを使用してアプリケーションの出力を解釈し、テストの合否を判定します。ドメイン固有のロジックに合わせて、これらのエージェントをカスタマイズできます。
デフォルトの解釈エージェント:
- 生の出力(テキスト、HTML、スクリーンショット)を観察します
- 一般的な推論を適用して期待を検証します
- 説明とともに合格/不合格を返します
カスタム解釈エージェント(examples/custom-agents/custom-comprehension-agent.yamlを参照):
scenario:
name: "Financial Dashboard Test with Custom Agent"
type: web
# Define custom comprehension logic
comprehension_agent:
model: "gpt-4"
system_prompt: |
You are a financial data validator. When verifying dashboard content:
1. All monetary values must use proper formatting ($1,234.56)
2. Percentages must include % symbol
3. Dates must be in MM/DD/YYYY format
4. Negative values must be red
5. Chart data must be logically consistent
Be strict about formatting and data consistency.
examples:
- input: "Total Revenue: 45000"
output: "FAIL - Missing currency symbol and comma separator"
- input: "Total Revenue: $45,000.00"
output: "PASS - Correctly formatted"
steps:
- action: navigate
url: "http://localhost:3000/financial-dashboard"
- action: verify_element
selector: ".revenue-widget"
use_custom_comprehension: true
description: "Revenue should be properly formatted"
ビジュアルリグレッションテスト [LEVEL 3]
スクリーンショットをベースライン画像と比較します:
scenario:
name: "Visual Regression - Homepage"
type: web
steps:
- action: navigate
url: "http://localhost:3000"
- action: wait_for_element
selector: ".page-loaded"
- action: screenshot
save_as: "homepage.png"
- action: visual_compare
screenshot: "homepage.png"
baseline: "./baselines/homepage-baseline.png"
threshold: 0.05 # 5% difference allowed
highlight_differences: true
パフォーマンス検証 [LEVEL 3]
パフォーマンス指標を測定して検証します:
scenario:
name: "Performance - Dashboard Load Time"
type: web
performance:
metrics:
- page_load_time
- first_contentful_paint
- time_to_interactive
steps:
- action: navigate
url: "http://localhost:3000/dashboard"
measure_timing: true
- action: verify_performance
metric: page_load_time
less_than: 3000 # 3 seconds
- action: verify_performance
metric: first_contentful_paint
less_than: 1500 # 1.5 seconds
複数ウィンドウの連携(Electron)[LEVEL 3]
複数のウィンドウを持つアプリケーションをテストします:
scenario:
name: "Multi-Window Chat Application"
type: electron
steps:
- action: launch
target: "./chat-app"
- action: menu_click
path: ["Window", "New Chat"]
- action: verify_window
count: 2
- action: window_action
window: 1
action: focus
- action: type
selector: ".message-input"
value: "Hello from window 1"
- action: click
selector: ".send-button"
- action: window_action
window: 2
action: focus
- action: wait_for_element
selector: ".message"
contains: "Hello from window 1"
timeout: 5s
IPC テスト(Electron)[LEVEL 3]
レンダラーとメインプロセス間のプロセス間通信をテストします:
scenario:
name: "Electron IPC Communication"
type: electron
steps:
- action: launch
target: "./my-app"
- action: ipc_send
channel: "get-system-info"
- action: ipc_expect
channel: "system-info-reply"
timeout: 3s
- action: verify_ipc_payload
contains:
platform: "darwin"
arch: "x64"
カスタムレポーター [LEVEL 3]
カスタムテストレポートを生成します:
scenario:
name: "Test with Custom Reporting"
type: cli
reporting:
format: custom
template: "./report-template.html"
include:
- screenshots
- logs
- timing_data
- video_recording
email:
enabled: true
recipients: ["[email protected]"]
on_failure_only: true
steps:
# ... test steps ...
フレームワークとの統合 [LEVEL 2]
テストの実行
単一のテスト:
gadugi-test run test-scenario.yaml
複数のテスト:
gadugi-test run tests/*.yaml
オプションを指定する場合:
gadugi-test run test.yaml \
--verbose \
--evidence-dir ./test-evidence \
--retry 2 \
--timeout 60s
CI/CD との統合
GitHub Actions(.github/workflows/agentic-tests.yml):
name: Agentic Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install gadugi-agentic-test
run: npm install -g @gadugi/agentic-test
- name: Run tests
run: gadugi-test run tests/agentic/*.yaml
- name: Upload evidence
if: always()
uses: actions/upload-artifact@v3
with:
name: test-evidence
path: ./evidence/
エビデンスの収集
このフレームワークは、デバッグ用のエビデンスを自動的に収集します:
evidence/
scenario-name-20250116-093045/
├── scenario.yaml # Original test scenario
├── execution-log.json # Detailed execution log
├── screenshots/ # All captured screenshots
│ ├── step-1.png
│ ├── step-3.png
│ └── step-5.png
├── output-captures/ # CLI/TUI output
│ ├── stdout.txt
│ └── stderr.txt
├── timing.json # Performance metrics
└── report.html # Human-readable report
ベストプラクティス [LEVEL 2]
1. シンプルに始め、段階的に複雑にする
基本的なスモークテストから始め、詳細を追加します:
# Level 1: Basic smoke test
steps:
- action: launch
target: "./app"
- action: verify_output
contains: "Ready"
# Level 2: Add interaction
steps:
- action: launch
target: "./app"
- action: send_input
value: "command\n"
- action: verify_output
contains: "Success"
# Level 3: Add error handling and edge cases
steps:
- action: launch
target: "./app"
- action: send_input
value: "invalid\n"
- action: verify_output
contains: "Error"
- action: send_input
value: "command\n"
- action: verify_output
contains: "Success"
2. わかりやすい名前と説明を使う
# Bad
scenario:
name: "Test 1"
steps:
- action: click
selector: "button"
# Good
scenario:
name: "User Login Flow - Valid Credentials"
description: "Verifies user can log in with valid email and password"
steps:
- action: click
selector: "button[type=submit]"
description: "Submit login form"
3. 重要なパスだけを検証する
細かな点をすべてテストする必要はありません。ユーザーに見える動作に注目します:
# Bad - Tests implementation details
- action: verify_element
selector: ".internal-cache-status"
contains: "initialized"
# Good - Tests user-visible behavior
- action: verify_element
selector: ".welcome-message"
contains: "Welcome back"
4. テストの依存関係には前提条件を使う
scenario:
name: "User Profile Edit"
prerequisites:
- "User [email protected] exists"
- "User is logged in"
- "Database is seeded with test data"
steps:
# Test assumes prerequisites are met
- action: navigate
url: "/profile"
5. テストを独立させる
各テストで独自の状態をセットアップし、後処理を行います:
scenario:
name: "Create Document"
steps:
# Create test user (don't assume exists)
- action: api_call
endpoint: "/api/users"
method: POST
data: { email: "[email protected]" }
# Run test
- action: navigate
url: "/documents/new"
# ... test steps ...
cleanup:
# Remove test user
- action: api_call
endpoint: "/api/users/[email protected]"
method: DELETE
6. 整理にはタグを使う
scenario:
name: "Critical Payment Flow"
tags: [smoke, critical, payment, e2e]
# Run with: gadugi-test run --tags critical
7. タイムアウトを適切に設定する
steps:
# Quick operations - short timeout
- action: click
selector: "button"
timeout: 2s
# Network operations - longer timeout
- action: wait_for_element
selector: ".data-loaded"
timeout: 10s
# Complex operations - generous timeout
- action: verify_element
selector: ".report-generated"
timeout: 60s
テスト戦略 [LEVEL 2]
スモークテスト
重要な機能が動作することを確認する最小限のテストです:
scenario:
name: "Smoke Test - Application Starts"
tags: [smoke]
steps:
- action: launch
target: "./app"
- action: verify_output
contains: "Ready"
timeout: 5s
各コミット前に実行します:gadugi-test run --tags smoke
ハッピーパステスト
理想的なユーザージャーニーをテストします:
scenario:
name: "Happy Path - User Registration"
steps:
- action: navigate
url: "/register"
- action: type
selector: "#email"
value: "[email protected]"
- action: type
selector: "#password"
value: "SecurePass123!"
- action: click
selector: "button[type=submit]"
- action: wait_for_url
contains: "/welcome"
エラーパステスト
エラー処理を検証します:
scenario:
name: "Error Path - Invalid Login"
steps:
- action: navigate
url: "/login"
- action: type
selector: "#email"
value: "[email protected]"
- action: type
selector: "#password"
value: "wrongpassword"
- action: click
selector: "button[type=submit]"
- action: verify_element
selector: ".error-message"
contains: "Invalid credentials"
リグレッションテスト
バグの再発を防ぎます:
scenario:
name: "Regression - Issue #123 Password Reset"
tags: [regression, bug-123]
description: "Verifies password reset email is sent (was broken in v1.2)"
steps:
- action: navigate
url: "/forgot-password"
- action: type
selector: "#email"
value: "[email protected]"
- action: click
selector: "button[type=submit]"
- action: verify_element
selector: ".success-message"
contains: "Reset email sent"
哲学との整合性 [LEVEL 2]
このスキルは、amplihack の中核原則に従っています:
徹底したシンプルさ
- コードより YAML:宣言型テストはプログラム型テストよりシンプルです
- 実装の詳細を含めない:テストでは「どのように」ではなく「何を」を記述します
- ボイラープレートを最小限にする:各テストは目的を絞り、簡潔にします
モジュール設計(ブリック&スタッド)
- 自己完結型のシナリオ:各 YAML ファイルは独立しています
- 明確な契約:ステップには明確に定義された入出力があります
- 組み合わせ可能なアクション:異なる種類のテスト間でアクションを再利用します
BS ゼロの実装
- スタブなし:このスキルの例はすべて、完全に実行可能なテストです
- 動作するデフォルト設定:最小限の設定でテストを実行できます
- 明確なエラー:フレームワークは対処可能なエラーメッセージを提示します
外側から考える
- ユーザーの視点:ユーザーが重視する動作をテストで検証します
- 実装に依存しない:リファクタリングによってテストが壊れることはありません
- 振る舞い駆動:内部の詳細ではなく、結果に注目します
よくある落とし穴と解決策 [LEVEL 2]
落とし穴 1:細かく指定しすぎる
問題:UI が少し変わるとテストが壊れます
# Bad - Too specific
- action: verify_element
selector: "div.container > div.row > div.col-md-6 > span.text-primary.font-bold"
contains: "Welcome"
解決策:柔軟なセレクターを使用します
# Good - Focused on behavior
- action: verify_element
selector: ".welcome-message"
contains: "Welcome"
落とし穴 2:待機の不足
問題:タイミングの問題により、テストが断続的に失敗します
# Bad - No wait for async operation
- action: click
selector: ".load-data-button"
- action: verify_element
selector: ".data-table" # May not exist yet!
解決策:動的コンテンツは必ず待機します
# Good - Wait for element to appear
- action: click
selector: ".load-data-button"
- action: wait_for_element
selector: ".data-table"
timeout: 10s
- action: verify_element
selector: ".data-table"
落とし穴 3:実装の詳細をテストする
問題:テストが内部状態に依存しています
# Bad - Tests internal cache state
- action: verify_output
contains: "Cache hit ratio: 85%"
解決策:ユーザーに見える動作をテストします
# Good - Tests response time
- action: verify_response_time
less_than: 100ms
description: "Fast response indicates caching works"
落とし穴 4:不安定なアサーション
問題:アサーションが厳密なタイミングや書式に依存しています
# Bad - Exact timestamp match will fail
- action: verify_output
contains: "Created at: 2025-11-16 09:30:45"
解決策:柔軟なパターンを使用します
# Good - Match pattern, not exact value
- action: verify_output
matches: "Created at: \\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}"
落とし穴 5:後片付けをしない
問題:テストが成果物を残し、以降の実行に影響します
# Bad - No cleanup
steps:
- action: create_file
path: "./test-data.json"
- action: launch
target: "./app"
解決策:必ずクリーンアップセクションを使用します
# Good - Cleanup ensures clean slate
steps:
- action: create_file
path: "./test-data.json"
- action: launch
target: "./app"
cleanup:
- action: delete_file
path: "./test-data.json"
サンプルライブラリ [LEVEL 1]
このスキルには、アプリケーションの種類と複雑さのレベルごとに整理された、完全に動作する15個のサンプルが含まれています。
CLI のサンプル
- calculator-basic.yaml [LEVEL 1] - CLI の基本的な算術演算
- cli-error-handling.yaml [LEVEL 2] - エラーメッセージと復旧
- cli-interactive-session.yaml [LEVEL 2] - 複数ターンの対話型 CLI
TUI のサンプル
- file-manager-navigation.yaml [LEVEL 1] - TUI の基本的なキーボード操作
- tui-form-validation.yaml [LEVEL 2] - 複雑なフォーム入力と検証
- tui-performance-monitoring.yaml [LEVEL 3] - TUI パフォーマンスダッシュボードのテスト
Web のサンプル
- dashboard-smoke-test.yaml [LEVEL 1] - Web ダッシュボードの簡単な検証
- web-authentication-flow.yaml [LEVEL 2] - 複数ステップのログインワークフロー
- web-visual-regression.yaml [LEVEL 2] - スクリーンショットを使用したビジュアルテスト
Electron のサンプル
- single-window-basic.yaml [LEVEL 1] - Electron ウィンドウの基本テスト
- multi-window-coordination.yaml [LEVEL 2] - 複数ウィンドウの連携
- electron-menu-testing.yaml [LEVEL 2] - アプリケーションメニューの操作
- electron-ipc-testing.yaml [LEVEL 3] - メイン/レンダラー間の IPC テスト
カスタムエージェントのサンプル
- custom-comprehension-agent.yaml [LEVEL 3] - ドメイン固有の検証ロジック
- custom-reporter-integration.yaml [LEVEL 3] - カスタムテストレポート
インラインドキュメント付きのサンプルコード全体については、examples/ ディレクトリを参照してください。
フレームワークの最新バージョン確認 [LEVEL 3]
このスキルには、gadugi-agentic-test バージョン 0.1.0 の情報が組み込まれています。新しいバージョンが存在するか確認するには、次のコマンドを実行します。
# Run the freshness check script
python scripts/check-freshness.py
# Output if outdated:
# WARNING: Embedded framework version is 0.1.0
# Latest GitHub version is 0.2.5
#
# New features in 0.2.5:
# - Native Playwright support for web testing
# - Video recording for all test types
# - Parallel test execution
#
# Update with: npm update -g @gadugi/agentic-test
スクリプトは GitHub リポジトリでリリースを確認し、組み込まれているバージョンと比較します。これにより、新機能や改善点を把握できます。
このスキルを更新するタイミング:
- 新しいフレームワークのバージョンで重要な機能が追加されたとき
- YAML スキーマに破壊的変更があったとき
- 新しいアプリケーションの種類がサポートされたとき
- エージェントの機能が拡張されたとき
他のスキルとの連携 [LEVEL 2]
相性の良いスキル
test-gap-analyzer:
- test-gap-analyzer を使って、未テストの関数を見つけます
- 重要なユーザー向け経路について、アウトサイドインテストを作成します
- 内部関数には、ユニットテスト(test-gap-analyzer によるもの)を使用します
philosophy-guardian:
- テストの YAML が徹底したシンプルさに従っていることを確認します
- テストが実装ではなく動作に焦点を当てていることを検証します
pr-review-assistant:
- PR レビューにアウトサイドインテストを含めます
- テストが変更された機能をカバーしていることを確認します
- テストの読みやすさと明瞭さを確認します
module-spec-generator:
- アウトサイドインテストのシナリオを含むモジュール仕様を生成します
- 仕様をテスト YAML のテンプレートとして使用します
組み合わせたワークフローの例
# 1. Analyze coverage gaps
claude "Use test-gap-analyzer on ./src"
# 2. Write outside-in tests for critical paths
claude "Use qa-team to create web tests for authentication"
# 3. Verify philosophy compliance
claude "Use philosophy-guardian to review new test files"
# 4. Include in PR
git add tests/agentic/
git commit -m "Add outside-in tests for auth flow"
トラブルシューティング [LEVEL 2]
テストがタイムアウトする
症状:テストがタイムアウトを超過して失敗します
原因:
- アプリケーションの起動に想定より時間がかかる
- ネットワークリクエストが遅い
- 要素が表示されない(セレクターが正しくない)
解決策:
# Increase timeout
- action: wait_for_element
selector: ".slow-loading-element"
timeout: 30s # Increase from default
# Add intermediate verification
- action: launch
target: "./app"
- action: wait_for_output
contains: "Initializing..."
timeout: 5s
- action: wait_for_output
contains: "Ready"
timeout: 20s
要素が見つからない
症状:verify_element または click が「element not found」で失敗します
原因:
- CSS セレクターが正しくない
- 要素がまだ描画されていない(タイミングの問題)
- 要素が iframe またはシャドウ DOM 内にある
解決策:
# Add wait before interaction
- action: wait_for_element
selector: ".target-element"
timeout: 10s
- action: click
selector: ".target-element"
# Use more specific selector
- action: click
selector: "button[data-testid='submit-button']"
# Handle iframe
- action: switch_to_iframe
selector: "iframe#payment-frame"
- action: click
selector: ".pay-now-button"
ローカルではテストが成功するが、CI では失敗する
症状:開発マシンではテストが動作するが、CI 環境では失敗します
原因:
- 画面サイズの違い(Web/Electron)
- 依存関係の不足
- タイミングの違い(CI マシンのほうが遅い)
- 環境変数の違い
解決策:
# Set explicit viewport size (web/Electron)
scenario:
environment:
viewport:
width: 1920
height: 1080
# Add longer timeouts in CI
- action: wait_for_element
selector: ".element"
timeout: 30s # Generous for CI
# Verify prerequisites
prerequisites:
- "Chrome browser installed"
- "Environment variable API_KEY is set"
出力が期待どおりではない
症状:出力が正しく見えるにもかかわらず、verify_output が失敗します
原因:
- 余分な空白や改行
- 出力に含まれる ANSI カラーコード
- 大文字と小文字の区別
解決策:
# Use flexible matching
- action: verify_output
matches: "Result:\\s+Success" # Allow flexible whitespace
# Strip ANSI codes
- action: verify_output
contains: "Success"
strip_ansi: true
# Case-insensitive match
- action: verify_output
contains: "success"
case_sensitive: false
参照:アクションカタログ [LEVEL 3]
CLI アクション
| アクション | パラメーター | 説明 |
|---|---|---|
launch | target, args, cwd, env | CLI アプリケーションを起動する |
send_input | value, delay | stdin にテキストを送信する |
send_signal | signal | OS シグナルを送信する(SIGINT、SIGTERM など) |
wait_for_output | contains, matches, timeout | stdout/stderr のテキストを待つ |
verify_output | contains, matches, stream | 出力内容を確認する |
verify_exit_code | expected | 終了コードを検証する |
capture_output | save_as, stream | 出力をファイルに保存する |
TUI アクション
| アクション | パラメーター | 説明 |
|---|---|---|
launch | target, args, terminal_size | TUI アプリケーションを起動する |
send_keypress | value, times, modifiers | キーボード入力を送信する |
wait_for_screen | contains, timeout | 画面上のテキストを待つ |
verify_screen | contains, matches, region | 画面の内容を確認する |
capture_screenshot | save_as | ターミナルのスクリーンショットを保存する |
navigate_menu | path | メニュー構造を移動する |
fill_form | fields | TUI のフォーム項目に入力する |
Web アクション
| アクション | パラメーター | 説明 |
|---|---|---|
navigate | url, wait_for_load | URL に移動する |
click | selector, text, nth | 要素をクリックする |
type | selector, value, delay | 入力欄にテキストを入力する |
wait_for_element | selector, timeout, disappears | 要素を待つ |
verify_element | selector, contains, count, exists | 要素の状態を確認する |
verify_url | equals, contains, matches | URL を検証する |
screenshot | save_as, selector, full_page | スクリーンショットを撮影する |
scroll | selector, direction, amount | ページ/要素をスクロールする |
select_option | selector, value | ドロップダウンの項目を選択する |
checkbox | selector, checked | チェックボックスをオン/オフにする |
Electron アクション
| アクション | パラメーター | 説明 |
|---|---|---|
launch | target, args, wait_for_window | Electron アプリを起動する |
window_action | window, action | ウィンドウを操作する |
menu_click | path | メニュー項目をクリックする |
dialog_action | type, action, filename | ダイアログを処理する |
ipc_send | channel, data | IPC メッセージを送信する |
ipc_expect | channel, timeout | IPC メッセージを待機する |
verify_window | title, visible, focused, count | ウィンドウの状態を確認する |
| すべての Web アクション | Electron には Chromium が含まれています |
共通パラメーター
| パラメーター | 型 | 説明 |
|---|---|---|
timeout | Duration | 最大待機時間(例:「5s」、「2m」) |
description | String | 人が読めるステップの説明 |
continue_on_failure | Boolean | ステップが失敗してもシナリオを失敗させない |
id | String | 条件分岐で使用するステップ識別子 |
condition | Expression | 条件が true の場合にのみステップを実行する |
クイックリファレンス:YAML テンプレート [LEVEL 1]
scenario:
# Required fields
name: "Test Name"
description: "What this test verifies"
type: cli | tui | web | electron
# Optional metadata
tags: [smoke, critical]
timeout: 60s
# What must be true before running
prerequisites:
- "Condition 1"
- "Condition 2"
# Environment setup
environment:
variables:
VAR_NAME: "value"
# Variables for templating
variables:
username: "testuser"
# Test steps (executed in order)
steps:
- action: launch
target: "./app"
- action: send_input
value: "command\n"
- action: verify_output
contains: "Success"
timeout: 5s
# Cleanup (always runs)
cleanup:
- action: stop_application
スキルの使用例 [LEVEL 1]
このスキルを呼び出す
Claude, use the qa-team skill to create a CLI test for my calculator app.
Claude, use qa-team to generate web tests for the login flow.
Claude, create TUI tests using the qa-team skill for file navigation.
得られるもの
- 要件に合った完全な YAML テストシナリオ
- 各セクションを説明するインラインドキュメント
- 適用済みのベストプラクティス(タイムアウト、待機、検証)
- 適切な複雑さのレベル(ニーズに応じて 1、2、または 3)
- テストの実行手順
リクエストと応答の例
ユーザー:「有効な認証情報を使用したユーザーログインの Web テストを作成してください」
Claude(このスキルを使用):
scenario:
name: "User Login - Valid Credentials"
description: "Verifies user can successfully log in with valid email and password"
type: web
tags: [smoke, auth, critical]
prerequisites:
- "User [email protected] exists with password 'TestPass123!'"
- "Application is running on http://localhost:3000"
steps:
# Navigate to login page
- action: navigate
url: "http://localhost:3000/login"
description: "Open login page"
# Wait for page to fully load
- action: wait_for_element
selector: "form.login-form"
timeout: 5s
description: "Wait for login form to render"
# Fill in email field
- action: type
selector: "input[name='email']"
value: "[email protected]"
description: "Enter email address"
# Fill in password field
- action: type
selector: "input[name='password']"
value: "TestPass123!"
description: "Enter password"
# Submit form
- action: click
selector: "button[type='submit']"
description: "Click login button"
# Wait for redirect to dashboard
- action: wait_for_url
contains: "/dashboard"
timeout: 10s
description: "Should redirect to dashboard after successful login"
# Verify user is logged in
- action: verify_element
selector: ".user-profile"
contains: "[email protected]"
description: "User email should appear in profile widget"
# Capture evidence
- action: screenshot
save_as: "successful-login.png"
description: "Save screenshot of logged-in state"
# To run this test:
# 1. Save as test-login-valid.yaml
# 2. Run: gadugi-test run test-login-valid.yaml
# 3. Check evidence in ./evidence/user-login-valid-credentials-TIMESTAMP/
関連リソース [LEVEL 1]
公式ドキュメント
- GitHub リポジトリ:https://github.com/rysweet/gadugi-agentic-test
- フレームワークのドキュメント:リポジトリの README と docs/ フォルダーを参照
- 課題トラッカー:https://github.com/rysweet/MicrosoftHackathon2025-AgenticCoding/issues/1356
レベル 4:Shadow 環境との統合 [LEVEL 4]
分離された Shadow 環境で外部から内部へ向かうテストを実行し、プッシュ前に変更を検証します。これにより、gadugi-agentic-test の動作テスト機能と Shadow 環境のクリーンな状態での分離を組み合わせられます。
テストに Shadow 環境を使用する理由
- クリーンな状態:新しいコンテナーを使用し、ホスト環境を汚染しません
- ローカルの変更:コミットしていないコードをそのままテストします
- 複数のリポジトリ:複数のリポジトリにまたがる変更を調整します
- CI との同等性:Shadow で確認される内容 ≈ CI で確認される内容
Shadow テストのワークフロー
Shadow 環境の詳細なドキュメントについては、shadow-testing スキルを参照してください。外部から内部へ向かうテストと統合する方法は次のとおりです。
パターン 1:Shadow 内での CLI テスト(Amplifier)
# Create shadow with your local library changes
shadow.create(local_sources=["~/repos/my-lib:org/my-lib"])
# Run outside-in test scenarios inside shadow
shadow.exec(shadow_id, "gadugi-test run test-scenario.yaml")
# Extract evidence
shadow.extract(shadow_id, "/evidence", "./test-evidence")
# Cleanup
shadow.destroy(shadow_id)
パターン 2:Shadow 内での CLI テスト(スタンドアロン)
# Create shadow with local changes
amplifier-shadow create --local ~/repos/my-lib:org/my-lib --name test
# Run your test scenarios
amplifier-shadow exec test "gadugi-test run test-scenario.yaml"
# Extract results
amplifier-shadow extract test /evidence ./test-evidence
# Cleanup
amplifier-shadow destroy test
パターン 3:複数リポジトリの統合テスト
# test-multi-repo.yaml
scenario:
name: "Multi-Repo Integration Test"
type: cli
prerequisites:
- "Shadow environment with core-lib and cli-tool"
steps:
- action: launch
target: "cli-tool"
- action: send_input
value: "process --lib core-lib\n"
- action: verify_output
contains: "Success: Using core-lib"
# Setup shadow with both repos
amplifier-shadow create \
--local ~/repos/core-lib:org/core-lib \
--local ~/repos/cli-tool:org/cli-tool \
--name multi-test
# Run test that exercises both
amplifier-shadow exec multi-test "gadugi-test run test-multi-repo.yaml"
パターン 4:Shadow 内での Web アプリのテスト
# test-web-app.yaml
scenario:
name: "Web App with Local Library"
type: web
steps:
- action: navigate
url: "http://localhost:3000"
- action: click
selector: "button.process"
- action: verify_element
selector: ".result"
contains: "Processed with v2.0" # Your local version
# Shadow with library changes
amplifier-shadow create --local ~/repos/my-lib:org/my-lib --name web-test
# Start web app inside shadow (uses your local lib)
amplifier-shadow exec web-test "
cd /workspace &&
git clone https://github.com/org/web-app &&
cd web-app &&
npm install && # Pulls your local my-lib via git URL rewriting
npm start &
"
# Wait for app to start, then run tests
amplifier-shadow exec web-test "sleep 5 && gadugi-test run test-web-app.yaml"
検証のベストプラクティス
Shadow 内でテストを実行するときは、常にローカルソースが使用されていることを確認してください。
# After shadow.create, check snapshot commits
shadow.status(shadow_id)
# Shows: snapshot_commits: {"org/my-lib": "abc1234..."}
# When your test installs dependencies, verify commit matches
# Look in test output for: my-lib @ git+...@abc1234
完全な例:ライブラリの変更の検証
# test-library-change.yaml - Outside-in test
scenario:
name: "Validate Library Breaking Change"
type: cli
description: "Test that dependent app still works with new library API"
steps:
- action: launch
target: "/workspace/org/dependent-app/cli.py"
- action: send_input
value: "process data.json\n"
- action: verify_output
contains: "Processed successfully"
description: "New library API should still work"
- action: verify_exit_code
expected: 0
# Complete workflow
# 1. Create shadow with your breaking change
amplifier-shadow create --local ~/repos/my-lib:org/my-lib --name breaking-test
# 2. Install dependent app (pulls your local lib)
amplifier-shadow exec breaking-test "
cd /workspace &&
git clone https://github.com/org/dependent-app &&
cd dependent-app &&
pip install -e . && # This installs git+https://github.com/org/my-lib (your local version)
echo 'Ready to test'
"
# 3. Run outside-in test
amplifier-shadow exec breaking-test "gadugi-test run test-library-change.yaml"
# If test passes, your breaking change is compatible!
# If test fails, you've caught the issue before pushing
シャドウ統合を使用するタイミング
次の場合は、シャドウと外側から内側へのテストを使用します。
- ✅ 依存プロジェクトと連携したライブラリの変更をテストする
- ✅ 複数リポジトリにまたがる協調的な変更を検証する
- ✅ プッシュ前にクリーンな状態で検証する必要がある
- ✅ 統合に関する問題を早期に検出したい
- ✅ セットアップ/インストール手順が機能することをテストする
次の場合は、シャドウを使用しないでください。
- ❌ 単純なユニットテスト(オーバーヘッドが大きすぎます)
- ❌ すでにコミット済みのコードのテスト(シャドウを使ってもメリットはありません)
- ❌ パフォーマンステスト(コンテナーのオーバーヘッドによって結果が歪みます)
詳細情報
以下を含む、シャドウ環境の詳細なドキュメントについては、
- DIY セットアップ用のシェルスクリプト
- Docker Compose の例
- 複数言語のサポート(Python、Node、Rust、Go)
- トラブルシューティングと検証の手法
shadow-testing スキルを読み込みます。
Claude, use the shadow-testing skill to set up a shadow environment
Amplifier ユーザーの場合、シャドウツールは組み込みです。
shadow.create(local_sources=["~/repos/lib:org/lib"])
関連スキル
- shadow-testing:シャドウ環境のセットアップと使用方法の詳細
- test-gap-analyzer:テストされていないコードパスを検出します
- philosophy-guardian:テスト哲学への準拠をレビューします
- pr-review-assistant:PR レビューにテストを含めます
- module-spec-generator:テストシナリオを含む仕様を生成します
参考資料
- 外側から内側へと内側から外側へのテストアプローチ
- ビヘイビア駆動開発(BDD)の原則
- AI を活用したテストのベストプラクティス
- テスト自動化のパターン
- シャドウ環境テストの手法
レベル 4:A/B 比較ハーネスと自己改善型監査 [LEVEL 4]
任意の 2 つの CLI 実装を並べて実行し、動作の違いを定量化するための再利用可能なツールです。次のように、2 つのものを比較する必要があるあらゆるシナリオで使用できます。
- 移行時の同等性:Python→Rust、v1→v2、モノリス→マイクロサービス
- A/B テスト:同じ CLI に対する 2 つのアプローチを比較する
- フィーチャーフラグの検証:同じバイナリで異なる設定を比較する
- バージョンのリグレッション:リリース N とリリース N+1 を比較する
- カナリアの検証:カナリアビルドと安定版を比較する
ツール
.claude/scenarios/ab-comparison/ にあります。
| ファイル | 目的 |
|---|---|
ab_comparison_harness.py | 2 つの CLI を分離されたサンドボックス内で並べて実行します |
ab_audit_cycle.py | 自己改善ループ:特定 → 分類 → 修正 → 再検証 |
SCENARIO_FORMAT.md | YAML シナリオ形式の仕様 |
example_scenario.yaml | 電卓 CLI のシナリオ例 |
クイックスタート
# Compare any two CLI implementations
python .claude/scenarios/ab-comparison/ab_comparison_harness.py \
--a "python -m myapp.cli" \
--b "./target/debug/myapp" \
--scenario tests/scenarios/*.yaml
# A/B with feature flag
python .claude/scenarios/ab-comparison/ab_comparison_harness.py \
--a "myapp --feature-flag=off" \
--b "myapp --feature-flag=on" \
--scenario tests/scenarios/regression.yaml
# Shadow mode: log divergences without failing (for production rollout)
python .claude/scenarios/ab-comparison/ab_comparison_harness.py \
--a "myapp-stable" \
--b "myapp-canary" \
--scenario tests/scenarios/*.yaml \
--shadow-mode \
--shadow-log /tmp/canary-divergences.jsonl
# Self-improving audit cycle (iterate until convergence)
python .claude/scenarios/ab-comparison/ab_audit_cycle.py \
--a "python -m myapp.cli" \
--b "./target/debug/myapp" \
--scenarios-dir tests/scenarios/
# Legacy flags (--legacy/--candidate) also work
python .claude/scenarios/ab-comparison/ab_comparison_harness.py \
--legacy "python -m myapp.cli" \
--candidate "./target/debug/myapp" \
--scenario tests/scenarios/*.yaml
シナリオ形式(概要)
cases:
- name: "unique-test-name"
category: "install" # For audit grouping
argv: ["subcommand", "--flag"] # Same args for both sides
timeout: 15 # Seconds
env:
PATH: "${SANDBOX_ROOT}/bin:${PATH}" # Template variables
setup: | # Bash script run in both sandboxes
mkdir -p bin
echo '#!/bin/bash' > bin/stub && chmod +x bin/stub
compare:
- exit_code # Integer match
- stdout # Text or JSON-semantic
- stderr # Text match
- "fs:path/to/file" # File/dir hash comparison
- "jsonfs:path/to/file.json" # JSON semantic comparison
完全な仕様については、SCENARIO_FORMAT.md を参照してください。
主な設計上の判断
-
分離されたサンドボックス:それぞれの側に独自の HOME、TMPDIR、PATH を割り当てます。2 つの実行間、またはホストとの間で衝突は発生しません。
-
JSON の意味的比較:
stdoutの比較では、可能であれば両側の出力を JSON として解析し、キーの順序を無視します。JSON でない場合は、完全一致するテキスト比較に切り替えます。 -
スタブバイナリのパターン:引数と環境変数をファイルに記録する偽のバイナリを提供してランチャーの動作をテストし、それらのファイルを比較します。
-
タイムアウトへの耐性:ハーネスをクラッシュさせるのではなく、タイムアウト時(終了コード 124)に部分的な出力を取得します。サンドボックス環境でハングする可能性のあるコマンドをテストする際に重要です。
-
シャドウモード:実行を失敗させずに、差異を追記専用の JSONL に記録します。ロールアウト中に実際のワークロードを監視するために使用します。
-
監査の分類:キーワードの推定に基づいて差異をグループ化し、優先順位を付けた修正作業ストリームの仕様を生成します。
自己改善サイクルのパターン
┌─────────────┐
│ IDENTIFY │ Run all scenarios, collect divergences
└──────┬──────┘
▼
┌─────────────┐
│ CATEGORIZE │ Group by area: install (5), launch (3), recipe (1)
└──────┬──────┘
▼
┌─────────────┐
│ SPECIFY │ Generate fix specs: [CRITICAL] fix-install, [HIGH] fix-launch
└──────┬──────┘
▼
┌─────────────┐
│ FIX │ Agent/human fixes code
└──────┬──────┘
▼
┌─────────────┐
│ RE-VALIDATE │ Run audit again → check progress (5→2 divergences)
└──────┬──────┘
▼
Converged? ──no──→ back to FIX
│
yes
▼
DONE
実環境での結果
amplihack-rs の移行検証に使用(rysweet/amplihack-rs#25):
- 118/118:12 の階層にわたる比較テスト
- 619/619:フックのゴールデンファイルテスト
- 9/9:シャドウハーネスのケース
- 5 件の Python のバグを発見して修正
- 1 件のレシピオーケストレーターのバグを発見して修正
- ランチャーの完全な動作一致を達成
変更履歴 [LEVEL 3]
Version 1.2.0 (2026-03-11)
- NEW: レベル 4 - A/B 比較ハーネスと自己改善型監査
- あらゆるサイドバイサイド CLI 比較に対応する汎用
ab_comparison_harness.py(移行の同等性、A/B テスト、機能フラグ、バージョンのリグレッション、カナリア) - 汎用の自己改善ループ
ab_audit_cycle.py SCENARIO_FORMAT.mdの YAML 仕様--a/--bフラグに対応(下位互換性のため--legacy/--candidateも使用可能)- シナリオファイルの例
- amplihack-rs の同等性検証から抽出(118/118 テスト)
Version 1.1.0 (2026-01-29)
- NEW: レベル 4 - シャドウ環境との統合
- シャドウテストのワークフローパターンを完全に追加
- Amplifier ネイティブ版およびスタンドアロン CLI の統合例
- 複数リポジトリの統合テストパターン
- シャドウ環境での Web アプリテスト
- ライブラリ変更の検証用ワークフロー例
- 詳細なドキュメントについて、シャドウテストスキルへの参照を追加
Version 1.0.0 (2025-11-16)
- スキルの初回リリース
- CLI、TUI、Web、Electron アプリケーションに対応
- 完全に動作する例を 15 件収録
- 段階的な開示レベル(1、2、3)
- gadugi-agentic-test フレームワークのドキュメントを埋め込み(v0.1.0)
- バージョン監視用の鮮度チェック スクリプト
- amplihack の理念との完全な統合
- 包括的なトラブルシューティングガイド
- アクション参照カタログ
覚えておいてください:アウトサイドインテストで検証するのは、アプリケーションが「何をするか」であり、「どのように実現するか」ではありません。ユーザーから見える動作に重点を置けば、リファクタリング後もテストの安定性を保ちながら、重要なワークフローを有意義に検証できます。
レベル 1 のシンプルなスモークテストから始め、必要な場合にだけ段階的に複雑さを加えてください。難しい部分はフレームワークの AI エージェントが処理します。何が起こるべきかを記述するだけです。