ステップアクションリファレンス
QA プランの各ステップは、http_request または browser の 2 つのアクションタイプのいずれかを実行します。AI エージェントが MCP ツールを通じて QA プランを構築する際に、これらのアクションを選択・設定します。このページでは、両方の完全な設定スキーマを説明します。
http_request
Section titled “http_request”http_request アクションは HTTP リクエストを送信し、レスポンスを検証します。
HttpRequestConfig
Section titled “HttpRequestConfig”| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
method | string | はい | HTTP メソッド:GET、POST、PUT、PATCH、DELETE など。 |
url | string | はい | リクエスト URL です。テンプレート変数をサポートします(例:{{base_url}}/api/users)。 |
headers | Record<string, string> | いいえ | キーバリューペアのリクエストヘッダーです。値はテンプレート変数をサポートします。ランナーはここに書かれたヘッダーをそのまま送信し、Content-Type も自動付与しません。詳細はヘッダーの取り扱いを参照。 |
body | RequestBody | いいえ | リクエストボディです。下記の discriminated union で任意の Content-Type を表現できます。旧形式(プレーン object → JSON、文字列 → text)も後方互換でサポート。 |
auth | HttpAuth | いいえ | 認証ヘルパー。指定すると対応する Authorization ヘッダーをランナーが組み立てます。詳細は認証を参照。 |
timeout | number | いいえ | リクエストタイムアウト(ミリ秒)です。 |
poll | PollConfig | いいえ | 条件が満たされるまでエンドポイントをポーリングします。 |
response_body | "auto" | "text" | "binary" | いいえ | レスポンス body の扱い方。auto(既定)は Content-Type で判定。text は強制的に UTF-8 デコード、binary は強制的にバイナリ扱い。 |
max_response_body_size | number | いいえ | レスポンス body から読み取る最大バイト数(既定 52428800 = 50MB)。超過時は body が打ち切られ body_truncated が立つ。 |
ヘッダーの取り扱い
Section titled “ヘッダーの取り扱い”ランナーはプランに書かれたヘッダーをそのまま送信し、body が構造化されていても Content-Type を自動付与しません。これは以下の QA ケースを表現可能にする意図的な設計です。
- ネガティブテスト —
Content-Typeと body を意図的にミスマッチさせ、サーバーが400/415を返すことを検証 - ベンダー固有 MIME —
application/vnd.api+json、application/ld+json、application/problem+json、application/cloudevents+jsonなど - charset 付き —
application/json; charset=utf-8等 Content-Typeを意図的に省略 — ヘッダー欠落時のサーバーのデフォルト挙動を検証
multipart body の場合、body の boundary フィールドと Content-Type: multipart/form-data; boundary=<同じ値> ヘッダーを両方書く必要があります(自動同期されません)。
「ヘッダーをそのまま送る」原則の唯一の例外が auth フィールドです。auth を指定すると Authorization ヘッダーがランナーによって自動生成されます。さらに headers 側に明示的な Authorization も書かれている場合、両方の Authorization ヘッダーがそのままワイヤに乗ります(ランナーは重複排除しません)。競合が表に出ることでネガティブテストとして表現可能になります。
auth フィールドはリクエストの認証意図を構造化して指定します。認証情報内のテンプレート変数を展開し、対応する Authorization ヘッダーを組み立て、既存のマスキングルールで artifact 記録前にヘッダー値を秘匿します。headers に直書きするのに比べ、シークレットがプラン中で読みやすく、base64 化を自分で行う必要がない利点があります。
type | フィールド | 生成されるヘッダー |
|---|---|---|
basic | username, password | Authorization: Basic <base64(username:password)> (RFC 7617) |
bearer | token | Authorization: Bearer <token> (RFC 6750) |
すべての認証情報フィールドは {{variable}} テンプレート展開をサポートするため、環境ファイルの secrets として管理できます。
Basic 認証:
{ "method": "GET", "url": "{{api_base_url}}/admin", "auth": { "type": "basic", "username": "{{admin_user}}", "password": "{{admin_password}}" }}Bearer トークン:
{ "method": "GET", "url": "{{api_base_url}}/me", "auth": { "type": "bearer", "token": "{{access_token}}" }}auth と headers.Authorization が両方ある場合の挙動についてはヘッダーの取り扱いを参照。
リクエスト Body 形式
Section titled “リクエスト Body 形式”body は type による discriminated union です。実際にワイヤに乗せたい形式を明示します。
type | 用途 | 必須フィールド |
|---|---|---|
json | 通常の JSON(REST API の大半)。値が JSON.stringify される | value(任意の JSON 値) |
form | application/x-www-form-urlencoded のフォーム送信(ログインフォーム、OAuth トークン交換) | fields: Record<string, string> |
multipart | multipart/form-data(ファイルアップロード、HTML フォーム送信) | fields?、files?、boundary? |
text | 生テキスト body(XML/SOAP、プレーンテキスト webhook 等) | value: string |
binary | 生バイナリ(画像/PDF の PUT、application/octet-stream アップロード) | path または content_base64 のいずれか1つ |
graphql | GraphQL クエリエンベロープ(JSON の糖衣) | query、任意で variables / operationName |
旧形式(後方互換)
Section titled “旧形式(後方互換)”discriminated union 以前に書かれたプランも引き続き動作します:プレーン object は { type: "json", value: <object> }、プレーン文字列は { type: "text", value: <string> } に正規化されます。新規プランは明示形式の使用を推奨します。
JSON POST:
{ "method": "POST", "url": "{{api_base_url}}/users", "headers": { "Content-Type": "application/json" }, "body": { "type": "json", "value": { "name": "Alice", "email": "alice@example.com" } }}Form-urlencoded:
{ "method": "POST", "url": "{{api_base_url}}/login", "headers": { "Content-Type": "application/x-www-form-urlencoded" }, "body": { "type": "form", "fields": { "username": "{{user}}", "password": "{{password}}" } }}Multipart ファイルアップロード:
{ "method": "POST", "url": "{{api_base_url}}/upload", "headers": { "Content-Type": "multipart/form-data; boundary=----aqua-b" }, "body": { "type": "multipart", "boundary": "----aqua-b", "fields": { "title": "report" }, "files": [ { "name": "file", "path": "./fixtures/sample.pdf", "filename": "sample.pdf", "content_type": "application/pdf" } ] }}各ファイルエントリは path(cwd からの相対パス)、content(インライン UTF-8 テキスト)、content_base64(インラインバイナリ)のうちちょうど1つを指定します。
生テキスト(XML / SOAP):
{ "method": "POST", "url": "{{api_base_url}}/soap", "headers": { "Content-Type": "application/xml" }, "body": { "type": "text", "value": "<envelope>...</envelope>" }}生バイナリ(画像 PUT):
{ "method": "PUT", "url": "{{api_base_url}}/avatar", "headers": { "Content-Type": "image/png" }, "body": { "type": "binary", "path": "./fixtures/avatar.png" }}binary body は path または content_base64 のうちちょうど1つを指定します。
GraphQL:
{ "method": "POST", "url": "{{api_base_url}}/graphql", "headers": { "Content-Type": "application/json" }, "body": { "type": "graphql", "query": "query Q($id: ID!) { user(id: $id) { name } }", "variables": { "id": "u_1" } }}レスポンス body の取り扱い
Section titled “レスポンス body の取り扱い”HTTP ドライバーはレスポンスの Content-Type ヘッダーで text/binary を判定します。text/*、application/json、application/xml、application/*+json、application/*+xml は text 扱い、それ以外はバイナリ扱いです。
バイナリレスポンスの場合:
- body は UTF-8 デコードされず、生バイトとして別の
http_response_bodyアーティファクトに保存されます(Web UI からダウンロード可能。画像と PDF はプレビュー可能) json_pathアサーション、body_containsアサーション、extractは常に失敗 / 何も返しません — 代わりにheader、body_size、body_hashアサーションを使用してください- レスポンスはストリーミングで読み込まれ、
max_response_body_sizeでキャップされます。超過時は body が打ち切られ、アサーションは受信済みのバイトに対して評価されます
SHA-256 ハッシュとバイト数は text/binary を問わず常に計算されるため、body_size と body_hash アサーションはどちらでも統一的に使えます。
PollConfig
Section titled “PollConfig”一部の API エンドポイントではポーリングが必要です。条件が満たされるまでリクエストを繰り返します。poll を指定すると、until 条件が満たされるかタイムアウトに達するまで、一定間隔でリクエストが繰り返されます。
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
until | object | はい | チェックする条件です。以下のサブフィールドのいずれかを指定する必要があります。 |
until.status_code | number | いいえ | レスポンスステータスコードがこの値と一致するまでポーリングします。 |
until.json_path | object | いいえ | レスポンスボディの JSON パスが一致するまでポーリングします。path(文字列)と expected(任意)を含みます。 |
interval_ms | number | はい | 各ポーリングリクエスト間の待機時間(ミリ秒)です。 |
timeout_ms | number | はい | ポーリングが失敗とみなされるまでの最大合計時間(ミリ秒)です。 |
ポーリングの例 — 非同期ジョブの完了を待機:
{ "action": "http_request", "config": { "method": "GET", "url": "{{api_base_url}}/jobs/{{job_id}}" }, "poll": { "until": { "json_path": "$.status", "equals": "completed" }, "interval_ms": 2000, "timeout_ms": 60000 }}Extract
Section titled “Extract”extract フィールドは HTTP レスポンスから値をキャプチャし、後続のステップで使用できるようにします。各抽出は JSONPath 式を使用してレスポンスボディ内の値を特定します。抽出された値は {{variable_name}} でアクセス可能なテンプレート変数になります。
{ "extract": { "user_id": "$.data.id", "user_name": "$.data.name" }}このステップの実行後、{{user_id}} と {{user_name}} がすべての後続ステップで利用可能になります。
以下の例では、ユーザーを作成し、返された ID を抽出した後、ユーザーを取得して正しく作成されたことを検証します。
ステップ 1 — ユーザーの作成:
{ "step_key": "create_user", "action": "http_request", "config": { "method": "POST", "url": "{{api_base_url}}/users", "headers": { "Content-Type": "application/json", "Authorization": "Bearer {{auth_token}}" }, "body": "{\"name\": \"Test User\", \"email\": \"test@example.com\"}" }, "assertions": [ { "type": "status_code", "expected": 201 }, { "type": "json_path", "expression": "$.data.name", "equals": "Test User" } ], "extract": { "created_user_id": "$.data.id" }}ステップ 2 — ユーザーの取得:
{ "step_key": "get_user", "action": "http_request", "depends_on": ["create_user"], "config": { "method": "GET", "url": "{{api_base_url}}/users/{{created_user_id}}", "headers": { "Authorization": "Bearer {{auth_token}}" } }, "assertions": [ { "type": "status_code", "expected": 200 }, { "type": "json_path", "expression": "$.data.email", "equals": "test@example.com" } ]}ステップ条件
Section titled “ステップ条件”ステップの condition フィールドは、変数の値に基づいてステップを実行するかどうかを制御します。条件が満たされない場合、ステップはスキップされます(depends_on や requires によるスキップと同じ動作です)。
条件チェックは depends_on のチェック後に評価されます。条件で参照する変数は通常、先行ステップの extract から取得します。
ConditionConfig
Section titled “ConditionConfig”| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
type | string | はい | 条件タイプ:"variable_equals" または "variable_not_equals" です。 |
variable | string | はい | チェックする変数名です。 |
value | string | はい | 比較する値です。 |
variable_equals
Section titled “variable_equals”変数が指定された値と等しい場合のみステップを実行します。変数が未定義の場合、条件は満たされず、ステップはスキップされます。
{ "condition": { "type": "variable_equals", "variable": "user_role", "value": "admin" }}variable_not_equals
Section titled “variable_not_equals”変数が指定された値と等しくない場合のみステップを実行します。変数が未定義の場合、条件は満たされ、ステップは実行されます。
{ "condition": { "type": "variable_not_equals", "variable": "payment_method", "value": "free" }}browser
Section titled “browser”browser アクションは、Playwright を使用してヘッドレスブラウザを操作します。
BrowserConfig
Section titled “BrowserConfig”| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
steps | BrowserStep[] | はい | 実行するブラウザアクションの順序付き配列です。 |
timeout_ms | number | いいえ | ブラウザアクションシーケンス全体の最大時間(ミリ秒)です。 |
ブラウザステップタイプ
Section titled “ブラウザステップタイプ”steps 配列の各エントリは、type フィールドとタイプ固有のパラメータを持つオブジェクトです。
ナビゲーション
Section titled “ナビゲーション”| タイプ | パラメータ | 説明 |
|---|---|---|
goto | string(URL) | URL に遷移します。テンプレート変数をサポートします。 |
マウスアクション
Section titled “マウスアクション”| タイプ | パラメータ | 説明 |
|---|---|---|
click | string(CSS セレクタ) | 要素をクリックします。 |
double_click | string(CSS セレクタ) | 要素をダブルクリックします。 |
hover | string(CSS セレクタ) | 要素にホバーします。 |
フォーム入力
Section titled “フォーム入力”| タイプ | パラメータ | 説明 |
|---|---|---|
type | { selector: string, text: string } | 入力フィールドにテキストを入力します。両方のフィールドでテンプレート変数をサポートします。 |
select_option | { selector: string, value: string } | <select> 要素で値を指定してオプションを選択します。 |
check | string(CSS セレクタ) | チェックボックスをチェックします。 |
uncheck | string(CSS セレクタ) | チェックボックスのチェックを外します。 |
press | { selector: string, key: string } | 要素にフォーカスした状態でキーボードキーを押します(例:Enter、Tab)。 |
focus | string(CSS セレクタ) | 要素にフォーカスします。 |
upload_file | { selector: string, path: string } | ファイル入力要素にファイルをアップロードします。 |
| タイプ | パラメータ | 説明 |
|---|---|---|
wait_for_selector | string(CSS セレクタ) | セレクタに一致する要素が DOM に表示されるまで待機します。 |
wait_for_url | string(URL 部分文字列) | ページの URL が指定した部分文字列を含むまで待機します。 |
| タイプ | パラメータ | 説明 |
|---|---|---|
screenshot | string(名前) | スクリーンショットを撮影し、指定した名前で保存します。 |
| タイプ | パラメータ | 説明 |
|---|---|---|
set_header | Record<string, string> | 後続のブラウザリクエストにカスタム HTTP ヘッダーを設定します。 |
| タイプ | パラメータ | 説明 |
|---|---|---|
switch_to_frame | string(CSS セレクタ) | セレクタで指定された iframe に実行コンテキストを切り替えます。 |
switch_to_main_frame | true | メインフレームに戻ります。 |
ブラウザコンテキストと状態
Section titled “ブラウザコンテキストと状態”ブラウザコンテキストは単一のシナリオ内のすべてのステップで共有されます。これは以下を意味します。
- ログインセッションはステップ間で維持されます。
- Cookie と localStorage は保持されます。
- ナビゲーション履歴は維持されます。
ブラウザの storageState(Cookie と localStorage)は、あるシナリオから次のシナリオに引き継がれます。これにより、初期のシナリオでログインを行い、認証フローを繰り返すことなく、以降のすべてのシナリオでそのセッションを利用できます。
以下の例では、ログインフローをテストし、ユーザーがダッシュボードに到達することを検証します。
ステップ 1 — ログイン:
{ "step_key": "login", "action": "browser", "config": { "steps": [ { "type": "goto", "url": "{{web_base_url}}/login" }, { "type": "type", "selector": "#email", "text": "{{test_email}}" }, { "type": "type", "selector": "#password", "text": "{{test_password}}" }, { "type": "click", "selector": "button[type='submit']" }, { "type": "wait_for_url", "url": "/dashboard" } ], "timeout_ms": 15000 }, "assertions": [ { "type": "url_contains", "expected": "/dashboard" }, { "type": "element_visible", "selector": "[data-testid='welcome-message']" } ]}ステップ 2 — ダッシュボードの内容を検証:
{ "step_key": "verify_dashboard", "action": "browser", "depends_on": ["login"], "config": { "steps": [ { "action": "wait_for_selector", "selector": "[data-testid='user-name']" } ] }, "assertions": [ { "type": "element_text", "selector": "[data-testid='user-name']", "expected": "Test User" }, { "type": "element_visible", "selector": "[data-testid='recent-activity']" } ]}