Test Scenario Schema Reference¶
The schema for test scenarios. Defines the complete structure for test steps, assertions, variables, execution metadata, and advanced features like retry policies and conditional branching.
Overview¶
The scenario schema defines the format for mobile test scenarios:
- Named string step IDs —
tap_login,wait_for_home(not integer indices) - 18 action types — From simple tap/type to advanced waits and variable capture
- 27 assertion types — Comprehensive UI, content, visual, and accessibility checks
- Variables & capture — Extract dynamic values during execution for later assertions
- Conditional execution — Optional steps, conditional branching, retry policies
- Structured preconditions — Setup actions and device state requirements
Schema version identifier: Every scenario carries a $schema_version field (note the leading $). It accepts "2.0" or "2.1" and defaults to "2.0". 2.1 is the current version and is purely additive over 2.0 — it adds the mode metadata field and four platform-agnostic semantic actions (press_back, dismiss_keyboard, grant_permission, deny_permission). Existing "2.0" scenarios remain valid; new scenarios should use "2.1".
Schema Structure Overview¶
Test Scenario
├─ Metadata
│ ├─ $schema_version (required: "2.0" or "2.1")
│ ├─ scenario_id (required: snake_case)
│ ├─ name (required: human-readable)
│ ├─ description (required: what it tests)
│ ├─ platform (required: android/ios/cross-platform)
│ ├─ app_package (required: bundle/package ID)
│ └─ metadata (required: app_version, environment)
├─ Organization
│ └─ tags (optional: filtering tags)
├─ Setup
│ ├─ variables (optional: variable definitions)
│ └─ preconditions (optional: setup actions)
├─ Execution
│ ├─ steps (required: ordered array of test actions)
│ └─ assertions (required: verification rules)
└─ Execution Metadata (runtime-only, in result schema)
Complete Field Reference¶
Root Level Fields¶
| Field | Type | Required | Description |
|---|---|---|---|
$schema_version |
string | YES | Accepts "2.0" or "2.1" (default "2.0"). "2.1" is current. |
scenario_id |
string | YES | Unique identifier in snake_case (e.g., login_happy_path) |
name |
string | YES | Human-readable scenario title |
description |
string | YES | What this scenario tests and business value |
platform |
string | YES | Target platform: android, ios, or cross-platform |
app_package |
string | YES | Android package name or iOS bundle identifier |
metadata |
object | YES | Design-time metadata with app_version and environment |
tags |
array | No | Categorization tags for filtering (max 10 tags, max 20 chars each) |
variables |
object | No | Variable declarations for capture_value steps |
preconditions |
object | No | Setup requirements and device actions before test |
steps |
array | YES | Ordered array of step objects (each with id, action, description) |
assertions |
array | YES | Array of assertion checks |
Example Minimal Scenario¶
{
"$schema_version": "2.1",
"scenario_id": "login_happy_path",
"name": "User Login - Happy Path",
"description": "Verify user can log in with valid credentials and access the dashboard",
"platform": "android",
"app_package": "com.example.app",
"metadata": {
"app_version": "1.2.3",
"environment": "staging"
},
"steps": [
{
"id": "tap_login_button",
"action": "tap",
"description": "Tap the login button on the welcome screen",
"target": "Login button"
},
{
"id": "wait_for_form",
"action": "wait_for_element",
"description": "Wait for the email input field to appear",
"target": "Email input field",
"wait_config": { "type": "element_visible", "timeout_ms": 5000 }
}
],
"assertions": [
{
"id": "login_form_visible",
"after_step": "wait_for_form",
"type": "element_exists",
"description": "The login form is displayed",
"element_description": "Email input field"
}
]
}
Steps Array¶
The steps field is an ordered array of step objects. Each object requires id, action, and description. The target field is a semantic description of the element (never a resource-id or OS-specific locator) — the agent resolves it to a tappable element at replay time.
Step ID Format¶
- Must be lowercase alphanumeric with underscores:
^[a-z][a-z0-9_]*$ - Examples:
tap_login,wait_for_home,type_email_address - Unique within the scenario; used for screenshot naming and
after_stepreferences
Action Types (18 total)¶
Each step's action field is one of these values: the 14 core actions documented below, plus 4 semantic actions available in platform-agnostic (mode: "platform-agnostic") scenarios — press_back, dismiss_keyboard, grant_permission, and deny_permission — which resolve to the right per-platform mechanics at replay time.
Note that clear_app_data is accepted by the schema but is not mechanically executable — the underlying automation engine exposes no primitive for it, so a scenario using it cannot replay unattended. The same applies to the enable_wifi and disable_wifi precondition device actions.
1. launch_app¶
Launch the app under test on the device.
Fields:
- action — "launch_app"
Example:
{
"id": "launch_app",
"action": "launch_app",
"description": "Launch the app under test"
}
2. tap¶
Tap on a UI element.
Fields:
- action — "tap"
- target — Semantic description of the element to tap
- optional (optional) — If true, step continues even if element not found (default: false)
- retry_policy (optional) — Retry configuration
Example:
{
"id": "tap_login_button",
"action": "tap",
"description": "Tap the login button",
"target": "Login button"
}
3. long_press¶
Long-press on a UI element.
Fields:
- action — "long_press"
- target — Element to long-press
Example:
{
"id": "long_press_menu_item",
"action": "long_press",
"description": "Long-press the list item to open the context menu",
"target": "First message in the list"
}
4. double_tap¶
Double-tap on a UI element.
Fields:
- action — "double_tap"
- target — Element to double-tap
Example:
{
"id": "double_tap_zoom",
"action": "double_tap",
"description": "Double-tap the image to zoom in",
"target": "Product image"
}
5. type¶
Type text into the currently focused input field.
Fields:
- action — "type"
- value — Text to type
Example:
{
"id": "enter_email",
"action": "type",
"description": "Type the account email into the focused field",
"value": "user@example.com"
}
6. swipe¶
Swipe/scroll in a direction.
Fields:
- action — "swipe"
- value — up, down, left, or right
Example:
{
"id": "scroll_down_page",
"action": "swipe",
"description": "Scroll down the page",
"value": "down"
}
7. scroll_to_element¶
Scroll until a specific element is visible.
Fields:
- action — "scroll_to_element"
- target — Element to scroll to
Example:
{
"id": "scroll_to_submit",
"action": "scroll_to_element",
"description": "Scroll until the submit button is on screen",
"target": "Submit button"
}
8. press_button¶
Press a hardware/virtual device button.
Fields:
- action — "press_button"
- value — BACK, HOME, or ENTER
Example:
{
"id": "press_back",
"action": "press_button",
"description": "Press the device back button",
"value": "BACK"
}
9. open_url¶
Open a URL (deep link or web) on the device.
Fields:
- action — "open_url"
- value — URL to open
Example:
{
"id": "open_help_page",
"action": "open_url",
"description": "Open the help page in the browser",
"value": "https://help.example.com"
}
10. wait_for_element¶
Wait until an element appears on screen.
Fields:
- action — "wait_for_element"
- target — Element to wait for
- wait_config — { "type": "element_visible", "timeout_ms": <1000–60000> }
Example:
{
"id": "wait_for_dashboard",
"action": "wait_for_element",
"description": "Wait for the dashboard content to appear",
"target": "Dashboard content",
"wait_config": { "type": "element_visible", "timeout_ms": 15000 }
}
11. wait_for_element_gone¶
Wait until an element disappears from screen.
Fields:
- action — "wait_for_element_gone"
- target — Element to wait for disappearance
- wait_config — { "type": "element_gone", "timeout_ms": <1000–60000> }
Example:
{
"id": "wait_for_loading_done",
"action": "wait_for_element_gone",
"description": "Wait for the loading spinner to disappear",
"target": "Loading spinner",
"wait_config": { "type": "element_gone", "timeout_ms": 20000 }
}
12. wait_for_loading_complete¶
Wait until loading indicators disappear.
Fields:
- action — "wait_for_loading_complete"
- wait_config — { "type": "loading_complete", "indicator": "any", "timeout_ms": <1000–60000> }
Note: indicator may be shimmer, spinner, progress_bar, skeleton, or any (default any).
Example:
{
"id": "wait_for_data_load",
"action": "wait_for_loading_complete",
"description": "Wait for the feed to finish loading",
"wait_config": { "type": "loading_complete", "indicator": "any", "timeout_ms": 30000 }
}
13. capture_value¶
Extract text/value from an element and store it in a variable.
Fields:
- action — "capture_value"
- target — Element to extract from
- capture_to — Variable name to store the value in (must be declared in the variables block)
Example:
{
"id": "capture_order_id",
"action": "capture_value",
"description": "Capture the order confirmation code",
"target": "Order confirmation code",
"capture_to": "order_id"
}
14. clear_app_data¶
Clear app data and cache (setup action).
Fields:
- action — "clear_app_data"
Example:
{
"id": "reset_app",
"action": "clear_app_data",
"description": "Clear app data to start from a clean state"
}
Step Field Options¶
Additional optional fields that can be added to any step object:
optional¶
If true, failure to find or interact with the target is silently ignored and execution continues. Default: false
{
"id": "optional_feature_check",
"action": "tap",
"description": "Dismiss the promo banner if it appears",
"target": "Promo banner close button",
"optional": true
}
retry_policy¶
Configure automatic retry behavior. Only applies when on_failure is "retry".
{
"id": "flaky_element_step",
"action": "wait_for_element",
"description": "Wait for the sometimes-slow element",
"target": "Slow-loading widget",
"wait_config": { "type": "element_visible", "timeout_ms": 10000 },
"on_failure": "retry",
"retry_policy": {
"max_attempts": 3,
"backoff_ms": 500
}
}
max_attempts— Total attempts including the first (integer, 2–5)backoff_ms— Milliseconds to wait between attempts (default1000)
condition¶
Execute the step only if the condition object evaluates to true; otherwise the step is skipped.
{
"id": "conditionally_submit",
"action": "tap",
"description": "Submit only when running on Android",
"target": "Submit button",
"condition": {
"type": "device_property",
"property": "platform",
"operator": "==",
"value": "android"
}
}
Condition type is one of device_property, previous_step_skipped, variable_value, or element_visible.
on_failure¶
What to do when the step fails: "fail" (default), "skip", or "retry".
{
"id": "critical_step",
"action": "tap",
"description": "Tap the critical confirm button",
"target": "Confirm button",
"on_failure": "fail"
}
sub_steps¶
A nested sub-flow (array of step objects) to execute when this step's condition is met. After the sub-steps complete, execution resumes at the next top-level step.
{
"id": "complex_flow",
"action": "tap",
"description": "Open the menu, then run the nested flow",
"target": "Menu button",
"sub_steps": [
{ "id": "tap_submenu", "action": "tap", "description": "Open the submenu", "target": "Settings submenu" },
{ "id": "verify_result", "action": "wait_for_element", "description": "Wait for the settings panel", "target": "Settings panel", "wait_config": { "type": "element_visible", "timeout_ms": 5000 } }
]
}
wait_config¶
Configuration for wait-type actions (wait_for_element, wait_for_element_gone, wait_for_loading_complete).
{
"id": "wait_step",
"action": "wait_for_element",
"description": "Wait for the confirmation banner",
"target": "Confirmation banner",
"wait_config": {
"type": "element_visible",
"timeout_ms": 5000
}
}
type—element_visible,element_gone, orloading_completetimeout_ms— Maximum wait in milliseconds (1000–60000)indicator(loading only) —shimmer,spinner,progress_bar,skeleton, orany
Variables Object¶
Declare variables that will be captured during test execution and used in assertions or conditions.
Format:
{
"variables": {
"variable_name": {
"type": "string|integer|number|boolean",
"description": "Human-readable description"
}
}
}
Example:
{
"variables": {
"auth_token": {
"type": "string",
"description": "Authentication token captured after login"
},
"user_id": {
"type": "integer",
"description": "User ID extracted from profile"
},
"is_premium": {
"type": "boolean",
"description": "Whether user has premium subscription"
}
}
}
Preconditions Object¶
Define setup requirements and device state before test execution.
Fields:
| Field | Type | Description |
|---|---|---|
app_state |
string | Required app state: fresh_install, logged_in, logged_out, any |
device_actions |
array | Automated setup actions to perform before the scenario starts |
device_properties |
object | Required device properties (network, location_services, orientation) |
notes |
array | Human-readable notes about preconditions that cannot be automated |
Each device_actions item has an action (clear_app_data, uninstall_app, install_app, enable_wifi, disable_wifi, set_orientation) plus optional target_package, value, and description.
Example:
{
"preconditions": {
"app_state": "logged_out",
"device_actions": [
{
"action": "clear_app_data",
"target_package": "com.example.app",
"description": "Clear any cached login data"
}
],
"device_properties": {
"network": "wifi",
"location_services": "enabled",
"orientation": "portrait"
},
"notes": ["A valid test account must exist in the staging environment"]
}
}
Assertions Array¶
Define verification rules that must pass for the test to succeed. Each assertion requires id, after_step, type, and description.
Fields:
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | YES | Unique assertion ID in snake_case |
after_step |
string | YES | The id of the step after which this assertion runs |
type |
string | YES | Assertion type (one of 27 types) |
description |
string | YES | Human-readable assertion description |
element_description |
string | Depends | Semantic description of the element to check (for element-based types) |
| Type-specific fields | varies | Depends | e.g., expected_value, expected_substring, expected_count, expected_text, pattern |
Example:
{
"assertions": [
{
"id": "welcome_message",
"after_step": "wait_for_home",
"type": "element_text",
"description": "Welcome message displays the user's name",
"element_description": "Welcome label",
"expected_value": "Welcome, John Doe"
},
{
"id": "dashboard_visible",
"after_step": "wait_for_home",
"type": "element_fully_visible",
"description": "Dashboard content is fully visible",
"element_description": "Dashboard content"
},
{
"id": "verification_code_format",
"after_step": "wait_for_home",
"type": "pattern_match",
"description": "Verification code has the correct format",
"element_description": "Verification code display",
"pattern": "^[0-9]{6}$"
}
]
}
See Assertion Types Reference for complete documentation on all 27 assertion types and their type-specific fields.
Metadata Object¶
Design-time metadata about the scenario. Runtime metadata (device, API level, timestamp) is captured in the result schema.
Fields:
| Field | Type | Required | Description |
|---|---|---|---|
app_version |
string | YES | Target app version (e.g., "1.2.3", "staging-latest") |
environment |
string | YES | Target environment: production, staging, development, etc. |
target_version |
string | No | Optional target major version (e.g., "v4.x") for compatibility |
Example:
{
"metadata": {
"app_version": "2.1.0",
"environment": "staging",
"target_version": "2.x"
}
}
Tags¶
Categorization tags for filtering and organizing scenarios.
Format:
- Lowercase alphanumeric with hyphens: ^[a-z0-9][a-z0-9-]*$
- Max 10 tags per scenario
- Max 20 characters per tag
Example:
{
"tags": ["smoke", "regression", "p0", "auth", "critical-flow"]
}
Common tag categories:
- Priority: p0, p1, p2, p3
- Type: smoke, regression, integration, sanity
- Feature: auth, checkout, payment, search
- Status: flaky, experimental, deprecated
Complete Example: Login Scenario with Variables¶
{
"$schema_version": "2.1",
"scenario_id": "login_with_2fa",
"name": "Login with 2FA",
"description": "Verify user can log in with email/password and complete two-factor authentication",
"platform": "android",
"app_package": "com.example.app",
"metadata": {
"app_version": "2.1.0",
"environment": "staging"
},
"tags": ["auth", "p0", "smoke"],
"variables": {
"auth_token": {
"type": "string",
"description": "JWT token received after successful login"
}
},
"preconditions": {
"app_state": "logged_out",
"device_actions": [
{
"action": "clear_app_data",
"target_package": "com.example.app",
"description": "Clear cached login data"
}
],
"notes": ["A valid test account must exist in the staging environment"]
},
"steps": [
{
"id": "launch_app",
"action": "launch_app",
"description": "Launch the app under test"
},
{
"id": "wait_for_login_screen",
"action": "wait_for_element",
"description": "Wait for the login screen to load",
"target": "Email input field",
"wait_config": { "type": "element_visible", "timeout_ms": 10000 }
},
{
"id": "tap_email_field",
"action": "tap",
"description": "Focus the email field",
"target": "Email input field"
},
{
"id": "enter_email",
"action": "type",
"description": "Type the test account email",
"value": "testuser@example.com"
},
{
"id": "tap_password_field",
"action": "tap",
"description": "Focus the password field",
"target": "Password input field"
},
{
"id": "type_password",
"action": "type",
"description": "Type the test account password",
"value": "SecurePassword123!"
},
{
"id": "tap_login",
"action": "tap",
"description": "Submit the login form",
"target": "Login button"
},
{
"id": "wait_for_2fa_prompt",
"action": "wait_for_element",
"description": "Wait for the two-factor code prompt",
"target": "2FA code input field",
"wait_config": { "type": "element_visible", "timeout_ms": 15000 },
"on_failure": "retry",
"retry_policy": { "max_attempts": 3, "backoff_ms": 1000 }
},
{
"id": "enter_2fa_code",
"action": "type",
"description": "Type the two-factor authentication code",
"value": "123456"
},
{
"id": "tap_verify",
"action": "tap",
"description": "Confirm the 2FA code",
"target": "Verify button"
},
{
"id": "wait_for_dashboard",
"action": "wait_for_loading_complete",
"description": "Wait for the dashboard to finish loading",
"wait_config": { "type": "loading_complete", "timeout_ms": 20000 }
},
{
"id": "capture_auth_token",
"action": "capture_value",
"description": "Capture the auth token from the session badge",
"target": "Auth token badge",
"capture_to": "auth_token"
}
],
"assertions": [
{
"id": "login_success",
"after_step": "wait_for_dashboard",
"type": "element_exists",
"description": "User successfully logged in and the dashboard is visible",
"element_description": "Dashboard content"
},
{
"id": "welcome_message",
"after_step": "wait_for_dashboard",
"type": "text_contains",
"description": "Welcome banner greets the user",
"element_description": "Welcome banner",
"expected_substring": "Welcome"
},
{
"id": "auth_token_captured",
"after_step": "capture_auth_token",
"type": "text_not_empty",
"description": "An auth token was captured",
"element_description": "Auth token badge"
},
{
"id": "dashboard_fully_loaded",
"after_step": "wait_for_dashboard",
"type": "element_fully_visible",
"description": "Dashboard content is fully visible",
"element_description": "Dashboard content"
}
]
}
Validation Rules¶
$schema_version:
- Accepts "2.0" or "2.1" (default "2.0"); "2.1" is current and additive
- Required
scenario_id:
- Format: ^[a-z][a-z0-9_]*$
- Unique within project
platform:
- One of: android, ios, cross-platform
app_package:
- Android: Java package format (e.g., com.example.app)
- iOS: Bundle identifier (e.g., com.example.App)
- Must be valid for target platform
Steps:
- steps is an array; each item requires id, action, and description
- All step IDs must follow format: ^[a-z][a-z0-9_]*$
- Step IDs must be unique within the scenario
- target values are semantic element descriptions, never resource-id / OS locators
Assertions:
- Each assertion requires id, after_step, type, and description
- after_step must reference a valid step id
- All assertion IDs must be unique
- type must be one of 27 supported types
Validate a scenario file at any time with mauto validate <file>, which returns the uniform envelope with data.valid.
Related References¶
- Assertion Types — All 27 assertion types with examples
- MCP Tools Reference — Device automation primitives
- Test Result Schema — How results are structured