
Qa Team
- 47 installs
- 70 repo stars
- Updated July 26, 2026
- rysweet/amplihack
Helps with ai & agent building tasks.
About
qa-team is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- qa-team
- AI & Agent Building
- AI-coding skill
Qa Team by the numbers
- 47 all-time installs (skills.sh)
- +1 installs in the week ending Jul 26, 2026 (Skillselion tracking)
- Ranked #7,461 of 16,556 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 2, 2026 (Skillselion catalog sync)
npx skills add https://github.com/rysweet/amplihack --skill qa-teamAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 47 |
|---|---|
| repo stars | ★ 70 |
| Last updated | July 26, 2026 |
| Repository | rysweet/amplihack ↗ |
What it does
Helps with ai & agent building tasks.
Files
QA Team Skill
Purpose [LEVEL 1]
This skill helps you create agentic outside-in tests that verify application behavior from an external user's perspective without any knowledge of internal implementation. Using the gadugi-agentic-test framework, you write declarative YAML scenarios that AI agents execute, observe, and validate.
Key Principle: Tests describe WHAT should happen, not HOW it's implemented. Agents figure out the execution details.
When to Use This Skill [LEVEL 1]
Perfect For
- Smoke Tests: Quick validation that critical user flows work
- Behavior-Driven Testing: Verify features from user perspective
- Cross-Platform Testing: Same test logic for CLI, TUI, Web, Electron
- Refactoring Safety: Tests remain valid when implementation changes
- AI-Powered Testing: Let agents handle complex interactions
- Documentation as Tests: YAML scenarios double as executable specs
Use This Skill When
- Starting a new project and defining expected behaviors
- Refactoring code and need tests that won't break with internal changes
- Testing user-facing applications (CLI tools, TUIs, web apps, desktop apps)
- Writing acceptance criteria that can be automatically verified
- Need tests that non-developers can read and understand
- Want to catch regressions in critical user workflows
- Testing complex multi-step interactions
Don't Use This Skill When
- Need unit tests for internal functions (use test-gap-analyzer instead)
- Testing performance or load characteristics
- Need precise timing or concurrency control
- Testing non-interactive batch processes
- Implementation details matter more than behavior
Core Concepts [LEVEL 1]
Outside-In Testing Philosophy
Traditional Inside-Out Testing:
# 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 stateAgentic Outside-In Testing:
# 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"Benefits:
- Tests survive refactoring (internal changes don't break tests)
- Readable by non-developers (YAML is declarative)
- Platform-agnostic (same structure for CLI/TUI/Web/Electron)
- AI agents handle complexity (navigation, timing, screenshots)
The Gadugi Agentic Test Framework [LEVEL 2]
Gadugi-agentic-test is a Python framework that:
1. Parses YAML test scenarios with declarative steps 2. Dispatches to specialized agents (CLI, TUI, Web, Electron agents) 3. Executes actions (launch, input, click, wait, verify) 4. Collects evidence (screenshots, logs, output captures) 5. Validates outcomes against expected results 6. Generates reports with evidence trails
Architecture:
YAML Scenario → Scenario Loader → Agent Dispatcher → Execution Engine
↓
[CLI Agent, TUI Agent, Web Agent, Electron Agent]
↓
Observers → Comprehension Agent
↓
Evidence ReportProgressive Disclosure Levels [LEVEL 1]
This skill teaches testing in four levels:
- Level 1: Fundamentals - Basic single-action tests, simple verification
- Level 2: Intermediate - Multi-step flows, conditional logic, error handling
- Level 3: Advanced - Custom agents, visual regression, performance validation
- Level 4: Parity & Shadowing - Side-by-side A/B comparison, remote observable runs, rollout divergence logging
Each example is marked with its level. Start at Level 1 and progress as needed.
Side-by-Side Parity and A/B Validation [LEVEL 2]
QA Team is the renamed primary skill for what used to be outside-in-testing. Use it for standard outside-in scenarios and for parity loops where you must compare a legacy implementation to a replacement, or compare approach A to approach B, as an external user would observe them.
Use QA Team for parity work when
- migrating Python to Rust, old CLI to new CLI, or v1 to v2 behavior
- validating a rewrite before switching defaults
- comparing branch A vs branch B using the same user scenarios
- running observable side-by-side sessions in paired virtual TTYs
- logging rollout divergences in shadow mode without failing the run
Recommended parity loop
1. Define shared user-facing scenarios first. 2. Run both implementations in isolated sandboxes. 3. Compare stdout, stderr, exit code, JSON outputs, and filesystem side effects. 4. Re-run in --observable mode when you need paired tmux panes for debugging. 5. Use --ssh-target <host> when parity must happen on a remote environment such as azlin. 6. Use --shadow-mode --shadow-log <file> during rollout to log divergences without blocking execution.
Command pattern to reuse
If the repo already has a parity harness, extend it instead of inventing a second one. A good baseline is:
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 \
--observableFor remote parity:
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-binaryFor rollout shadow logging:
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.jsonlQuick Start [LEVEL 1]
Installation
Prerequisites (for native module compilation):
# 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 the framework:
# 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 --versionYour First Test (CLI Example)
Create 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: 0Run the test:
gadugi-test run test-hello.yamlOutput:
✓ 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/Understanding the YAML Structure [LEVEL 1]
Every test scenario has this structure:
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_applicationApplication Types and Agents [LEVEL 2]
CLI Applications [LEVEL 1]
Use Case: Command-line tools, scripts, build tools, package managers
Supported Actions:
launch- Start the CLI programsend_input- Send text or commands via stdinsend_signal- Send OS signals (SIGINT, SIGTERM)wait_for_output- Wait for specific text in stdout/stderrverify_output- Check stdout/stderr contains/matches expected textverify_exit_code- Validate process exit codecapture_output- Save output for later verification
Example (see 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: 0TUI Applications [LEVEL 1]
Use Case: Terminal user interfaces (htop, vim, tmux, custom dashboard TUIs)
Supported Actions:
launch- Start TUI applicationsend_keypress- Send keyboard input (arrow keys, enter, ctrl+c, etc.)wait_for_screen- Wait for specific text to appear on screenverify_screen- Check screen contents match expectationscapture_screenshot- Save terminal screenshot (ANSI art)navigate_menu- Navigate menu structuresfill_form- Fill TUI form fields
Example (see 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 Applications [LEVEL 1]
Use Case: Web apps, dashboards, SPAs, admin panels
Supported Actions:
navigate- Go to URLclick- Click element by selector or texttype- Type into input fieldswait_for_element- Wait for element to appearverify_element- Check element exists/contains textverify_url- Validate current URLscreenshot- Capture browser screenshotscroll- Scroll page or element
Example (see 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 Applications [LEVEL 2]
Use Case: Desktop apps built with Electron (VS Code, Slack, Discord clones)
Supported Actions:
launch- Start Electron appwindow_action- Interact with windows (focus, minimize, close)menu_click- Click application menu itemsdialog_action- Handle native dialogs (open file, save, confirm)ipc_send- Send IPC message to main processverify_window- Check window state/properties- All web actions (since Electron uses Chromium)
Example (see 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"Test Scenario Anatomy [LEVEL 2]
Metadata Section
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
Prerequisites are conditions that must be true before the test runs. The framework validates these before execution.
prerequisites:
- "./application binary exists"
- "Port 8080 is available"
- "Database is running"
- "User account test@example.com exists"
- "File ./test-data.json exists"If prerequisites fail, the test is skipped (not failed).
Steps
Steps execute sequentially. Each step has:
- action: Required - the action to perform
- Parameters: Action-specific parameters
- description: Optional - human-readable explanation
- timeout: Optional - step-specific timeout
- continue_on_failure: Optional - don't fail scenario if step fails
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: trueVerification Actions [LEVEL 1]
Verification actions check expected outcomes. They fail the test if expectations aren't met.
Common Verifications:
# 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: trueCleanup Section
Cleanup runs after all steps complete (success or failure). Use for teardown actions.
cleanup:
- action: stop_application
force: true
- action: delete_file
path: "./temp-test-data.json"
- action: reset_database
connection: "test_db"Advanced Patterns [LEVEL 2]
Conditional Logic
Execute steps based on conditions:
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.passedVariables and Templating [LEVEL 2]
Define variables and use them throughout the scenario:
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}!"Loops and Repetition [LEVEL 2]
Repeat actions multiple times:
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"Error Handling [LEVEL 2]
Handle expected errors gracefully:
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: trueMulti-Step Workflows [LEVEL 2]
Complex scenarios with multiple phases:
scenario:
name: "E-commerce Purchase Flow"
type: web
steps:
# Phase 1: Authentication
- action: navigate
url: "http://localhost:3000/login"
- action: type
selector: "#username"
value: "test@example.com"
- 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: trueLevel 3: Advanced Topics [LEVEL 3]
Custom Comprehension Agents
The framework uses AI agents to interpret application output and determine if tests pass. You can customize these agents for domain-specific logic.
Default Comprehension Agent:
- Observes raw output (text, HTML, screenshots)
- Applies general reasoning to verify expectations
- Returns pass/fail with explanation
Custom Comprehension Agent (see 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"Visual Regression Testing [LEVEL 3]
Compare screenshots against baseline images:
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: truePerformance Validation [LEVEL 3]
Measure and validate performance metrics:
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 secondsMulti-Window Coordination (Electron) [LEVEL 3]
Test applications with multiple windows:
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: 5sIPC Testing (Electron) [LEVEL 3]
Test Inter-Process Communication between renderer and main:
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"Custom Reporters [LEVEL 3]
Generate custom test reports:
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: ["team@example.com"]
on_failure_only: true
steps:
# ... test steps ...Framework Integration [LEVEL 2]
Running Tests
Single test:
gadugi-test run test-scenario.yamlMultiple tests:
gadugi-test run tests/*.yamlWith options:
gadugi-test run test.yaml \
--verbose \
--evidence-dir ./test-evidence \
--retry 2 \
--timeout 60sCI/CD Integration
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 Collection
The framework automatically collects evidence for debugging:
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 reportBest Practices [LEVEL 2]
1. Start Simple, Add Complexity
Begin with basic smoke tests, then add detail:
# 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. Use Descriptive Names and Descriptions
# 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. Verify Critical Paths Only
Don't test every tiny detail. Focus on user-facing behavior:
# 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. Use Prerequisites for Test Dependencies
scenario:
name: "User Profile Edit"
prerequisites:
- "User testuser@example.com exists"
- "User is logged in"
- "Database is seeded with test data"
steps:
# Test assumes prerequisites are met
- action: navigate
url: "/profile"5. Keep Tests Independent
Each test should set up its own state and clean up:
scenario:
name: "Create Document"
steps:
# Create test user (don't assume exists)
- action: api_call
endpoint: "/api/users"
method: POST
data: { email: "test@example.com" }
# Run test
- action: navigate
url: "/documents/new"
# ... test steps ...
cleanup:
# Remove test user
- action: api_call
endpoint: "/api/users/test@example.com"
method: DELETE6. Use Tags for Organization
scenario:
name: "Critical Payment Flow"
tags: [smoke, critical, payment, e2e]
# Run with: gadugi-test run --tags critical7. Add Timeouts Strategically
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: 60sTesting Strategies [LEVEL 2]
Smoke Tests
Minimal tests that verify critical functionality works:
scenario:
name: "Smoke Test - Application Starts"
tags: [smoke]
steps:
- action: launch
target: "./app"
- action: verify_output
contains: "Ready"
timeout: 5sRun before every commit: gadugi-test run --tags smoke
Happy Path Tests
Test the ideal user journey:
scenario:
name: "Happy Path - User Registration"
steps:
- action: navigate
url: "/register"
- action: type
selector: "#email"
value: "newuser@example.com"
- action: type
selector: "#password"
value: "SecurePass123!"
- action: click
selector: "button[type=submit]"
- action: wait_for_url
contains: "/welcome"Error Path Tests
Verify error handling:
scenario:
name: "Error Path - Invalid Login"
steps:
- action: navigate
url: "/login"
- action: type
selector: "#email"
value: "invalid@example.com"
- action: type
selector: "#password"
value: "wrongpassword"
- action: click
selector: "button[type=submit]"
- action: verify_element
selector: ".error-message"
contains: "Invalid credentials"Regression Tests
Prevent bugs from reappearing:
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: "user@example.com"
- action: click
selector: "button[type=submit]"
- action: verify_element
selector: ".success-message"
contains: "Reset email sent"Philosophy Alignment [LEVEL 2]
This skill follows amplihack's core principles:
Ruthless Simplicity
- YAML over code: Declarative tests are simpler than programmatic tests
- No implementation details: Tests describe WHAT, not HOW
- Minimal boilerplate: Each test is focused and concise
Modular Design (Bricks & Studs)
- Self-contained scenarios: Each YAML file is independent
- Clear contracts: Steps have well-defined inputs/outputs
- Composable actions: Reuse actions across different test types
Zero-BS Implementation
- No stubs: Every example in this skill is a complete, runnable test
- Working defaults: Tests run with minimal configuration
- Clear errors: Framework provides actionable error messages
Outside-In Thinking
- User perspective: Tests verify behavior users care about
- Implementation agnostic: Refactoring doesn't break tests
- Behavior-driven: Focus on outcomes, not internals
Common Pitfalls and Solutions [LEVEL 2]
Pitfall 1: Over-Specifying
Problem: Test breaks when UI changes slightly
# Bad - Too specific
- action: verify_element
selector: "div.container > div.row > div.col-md-6 > span.text-primary.font-bold"
contains: "Welcome"Solution: Use flexible selectors
# Good - Focused on behavior
- action: verify_element
selector: ".welcome-message"
contains: "Welcome"Pitfall 2: Missing Waits
Problem: Test fails intermittently due to timing
# Bad - No wait for async operation
- action: click
selector: ".load-data-button"
- action: verify_element
selector: ".data-table" # May not exist yet!Solution: Always wait for dynamic content
# 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"Pitfall 3: Testing Implementation Details
Problem: Test coupled to internal state
# Bad - Tests internal cache state
- action: verify_output
contains: "Cache hit ratio: 85%"Solution: Test user-visible behavior
# Good - Tests response time
- action: verify_response_time
less_than: 100ms
description: "Fast response indicates caching works"Pitfall 4: Flaky Assertions
Problem: Assertions depend on exact timing or formatting
# Bad - Exact timestamp match will fail
- action: verify_output
contains: "Created at: 2025-11-16 09:30:45"Solution: Use flexible patterns
# Good - Match pattern, not exact value
- action: verify_output
matches: "Created at: \\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}"Pitfall 5: Not Cleaning Up
Problem: Tests leave artifacts that affect future runs
# Bad - No cleanup
steps:
- action: create_file
path: "./test-data.json"
- action: launch
target: "./app"Solution: Always use cleanup section
# 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"Example Library [LEVEL 1]
This skill includes 15 complete working examples organized by application type and complexity level:
CLI Examples
1. calculator-basic.yaml [LEVEL 1] - Simple CLI arithmetic operations 2. cli-error-handling.yaml [LEVEL 2] - Error messages and recovery 3. cli-interactive-session.yaml [LEVEL 2] - Multi-turn interactive CLI
TUI Examples
4. file-manager-navigation.yaml [LEVEL 1] - Basic TUI keyboard navigation 5. tui-form-validation.yaml [LEVEL 2] - Complex form filling and validation 6. tui-performance-monitoring.yaml [LEVEL 3] - TUI performance dashboard testing
Web Examples
7. dashboard-smoke-test.yaml [LEVEL 1] - Simple web dashboard verification 8. web-authentication-flow.yaml [LEVEL 2] - Multi-step login workflow 9. web-visual-regression.yaml [LEVEL 2] - Screenshot-based visual testing
Electron Examples
10. single-window-basic.yaml [LEVEL 1] - Basic Electron window test 11. multi-window-coordination.yaml [LEVEL 2] - Multiple window orchestration 12. electron-menu-testing.yaml [LEVEL 2] - Application menu interactions 13. electron-ipc-testing.yaml [LEVEL 3] - Main/renderer IPC testing
Custom Agent Examples
14. custom-comprehension-agent.yaml [LEVEL 3] - Domain-specific validation logic 15. custom-reporter-integration.yaml [LEVEL 3] - Custom test reporting
See examples/ directory for full example code with inline documentation.
Framework Freshness Check [LEVEL 3]
This skill embeds knowledge of gadugi-agentic-test version 0.1.0. To check if a newer version exists:
# 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-testThe script checks the GitHub repository for releases and compares against the embedded version. This ensures you're aware of new features and improvements.
When to Update This Skill:
- New framework version adds significant features
- Breaking changes in YAML schema
- New application types supported
- Agent capabilities expand
Integration with Other Skills [LEVEL 2]
Works Well With
test-gap-analyzer:
- Use test-gap-analyzer to find untested functions
- Write outside-in tests for critical user-facing paths
- Use unit tests (from test-gap-analyzer) for internal functions
philosophy-guardian:
- Ensure test YAML follows ruthless simplicity
- Verify tests focus on behavior, not implementation
pr-review-assistant:
- Include outside-in tests in PR reviews
- Verify tests cover changed functionality
- Check test readability and clarity
module-spec-generator:
- Generate module specs that include outside-in test scenarios
- Use specs as templates for test YAML
Example Combined Workflow
# 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"Troubleshooting [LEVEL 2]
Test Times Out
Symptom: Test exceeds timeout and fails
Causes:
- Application takes longer to start than expected
- Network requests are slow
- Element never appears (incorrect selector)
Solutions:
# 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: 20sElement Not Found
Symptom: verify_element or click fails with "element not found"
Causes:
- Incorrect CSS selector
- Element not yet rendered (timing issue)
- Element in iframe or shadow DOM
Solutions:
# 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"Test Passes Locally, Fails in CI
Symptom: Test works on dev machine but fails in CI environment
Causes:
- Different screen size (web/Electron)
- Missing dependencies
- Timing differences (slower CI machines)
- Environment variable differences
Solutions:
# 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"Output Doesn't Match Expected
Symptom: verify_output fails even though output looks correct
Causes:
- Extra whitespace or newlines
- ANSI color codes in output
- Case sensitivity
Solutions:
# 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: falseReference: Action Catalog [LEVEL 3]
CLI Actions
| Action | Parameters | Description |
|---|---|---|
launch | target, args, cwd, env | Start CLI application |
send_input | value, delay | Send text to stdin |
send_signal | signal | Send OS signal (SIGINT, SIGTERM, etc.) |
wait_for_output | contains, matches, timeout | Wait for text in stdout/stderr |
verify_output | contains, matches, stream | Check output content |
verify_exit_code | expected | Validate exit code |
capture_output | save_as, stream | Save output to file |
TUI Actions
| Action | Parameters | Description |
|---|---|---|
launch | target, args, terminal_size | Start TUI application |
send_keypress | value, times, modifiers | Send keyboard input |
wait_for_screen | contains, timeout | Wait for text on screen |
verify_screen | contains, matches, region | Check screen content |
capture_screenshot | save_as | Save terminal screenshot |
navigate_menu | path | Navigate menu structure |
fill_form | fields | Fill TUI form fields |
Web Actions
| Action | Parameters | Description |
|---|---|---|
navigate | url, wait_for_load | Go to URL |
click | selector, text, nth | Click element |
type | selector, value, delay | Type into input |
wait_for_element | selector, timeout, disappears | Wait for element |
verify_element | selector, contains, count, exists | Check element state |
verify_url | equals, contains, matches | Validate URL |
screenshot | save_as, selector, full_page | Capture screenshot |
scroll | selector, direction, amount | Scroll page/element |
select_option | selector, value | Select dropdown option |
checkbox | selector, checked | Check/uncheck checkbox |
Electron Actions
| Action | Parameters | Description |
|---|---|---|
launch | target, args, wait_for_window | Start Electron app |
window_action | window, action | Interact with windows |
menu_click | path | Click menu items |
dialog_action | type, action, filename | Handle dialogs |
ipc_send | channel, data | Send IPC message |
ipc_expect | channel, timeout | Wait for IPC message |
verify_window | title, visible, focused, count | Check window state |
| All web actions | Electron includes Chromium |
Common Parameters
| Parameter | Type | Description |
|---|---|---|
timeout | Duration | Maximum wait time (e.g., "5s", "2m") |
description | String | Human-readable step explanation |
continue_on_failure | Boolean | Don't fail scenario if step fails |
id | String | Step identifier for conditionals |
condition | Expression | Execute step only if condition true |
Quick Reference: YAML Template [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_applicationSkill Usage Examples [LEVEL 1]
Invoke This Skill
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.What You'll Get
1. Complete YAML test scenario matching your requirements 2. Inline documentation explaining each section 3. Best practices applied (timeouts, waits, verification) 4. Appropriate complexity level (1, 2, or 3 based on needs) 5. Instructions for running the test
Example Request and Response
User: "Create a web test for user login with valid credentials"
Claude (using this skill):
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 test@example.com 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: "test@example.com"
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: "test@example.com"
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/Related Resources [LEVEL 1]
Official Documentation
- GitHub Repository: https://github.com/rysweet/gadugi-agentic-test
- Framework Docs: See repo README and docs/ folder
- Issue Tracker: https://github.com/rysweet/MicrosoftHackathon2025-AgenticCoding/issues/1356
Level 4: Shadow Environment Integration [LEVEL 4]
Run your outside-in tests in isolated shadow environments to validate changes before pushing. This combines the behavioral testing power of gadugi-agentic-test with the clean-state isolation of shadow environments.
Why Use Shadow Environments for Testing
1. Clean State: Fresh container, no host pollution 2. Local Changes: Test uncommitted code exactly as-is 3. Multi-Repo: Coordinate changes across multiple repos 4. CI Parity: What shadow sees ≈ what CI will see
Shadow Testing Workflow
For complete shadow environment documentation, see the shadow-testing skill. Here's how to integrate it with outside-in tests:
Pattern 1: CLI Tests in Shadow (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)Pattern 2: CLI Tests in Shadow (Standalone)
# 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 testPattern 3: Multi-Repo Integration Test
# 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"Pattern 4: Web App Testing in Shadow
# 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"Verification Best Practices
When running tests in shadow, always verify your local sources are being used:
# 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+...@abc1234Complete Example: Library Change Validation
# 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 pushingWhen to Use Shadow Integration
Use shadow + outside-in tests when:
- ✅ Testing library changes with dependent projects
- ✅ Validating multi-repo coordinated changes
- ✅ Need clean-state validation before pushing
- ✅ Want to catch integration issues early
- ✅ Testing that setup/install procedures work
Don't use shadow for:
- ❌ Simple unit tests (too much overhead)
- ❌ Tests of already-committed code (shadow adds no value)
- ❌ Performance testing (container overhead skews results)
Learn More
For complete shadow environment documentation, including:
- Shell scripts for DIY setup
- Docker Compose examples
- Multi-language support (Python, Node, Rust, Go)
- Troubleshooting and verification techniques
Load the shadow-testing skill:
Claude, use the shadow-testing skill to set up a shadow environmentOr for Amplifier users, the shadow tool is built-in:
shadow.create(local_sources=["~/repos/lib:org/lib"])---
Related Skills
- shadow-testing: Complete shadow environment setup and usage
- test-gap-analyzer: Find untested code paths
- philosophy-guardian: Review test philosophy compliance
- pr-review-assistant: Include tests in PR reviews
- module-spec-generator: Generate specs with test scenarios
Further Reading
- Outside-in vs inside-out testing approaches
- Behavior-driven development (BDD) principles
- AI-powered testing best practices
- Test automation patterns
- Shadow environment testing methodology
Level 4: A/B Comparison Harness & Self-Improving Audit [LEVEL 4]
Reusable tools for running any two CLI implementations side-by-side and quantifying their behavioral differences. Works for any scenario where you need to compare two things:
- Migration parity: Python→Rust, v1→v2, monolith→microservice
- A/B testing: Compare two approaches to the same CLI
- Feature flag validation: Same binary, different configs
- Version regression: Compare release N with release N+1
- Canary validation: Compare canary build against stable
Tools
Located in .claude/scenarios/ab-comparison/:
| File | Purpose |
|---|---|
ab_comparison_harness.py | Run two CLIs side-by-side in isolated sandboxes |
ab_audit_cycle.py | Self-improving loop: identify → categorize → fix → re-validate |
SCENARIO_FORMAT.md | YAML scenario format specification |
example_scenario.yaml | Example scenario for a calculator CLI |
Quick Start
# 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/*.yamlScenario Format (Summary)
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 comparisonSee SCENARIO_FORMAT.md for the full specification.
Key Design Decisions
1. Isolated sandboxes: Each side gets its own HOME, TMPDIR, PATH. No collisions between the two runs, or with the host.
2. JSON-semantic comparison: stdout comparison parses both sides as JSON if possible, ignoring key ordering. Falls back to exact text if not JSON.
3. Stub binary pattern: Test launcher behavior by providing fake binaries that capture their args and env vars to files, then compare those files.
4. Timeout resilience: Captures partial output on timeout (exit code 124) instead of crashing the harness. Critical for testing commands that may hang in sandboxed environments.
5. Shadow mode: Logs divergences to append-only JSONL without failing the run. Use during rollout to monitor real workloads.
6. Audit categorization: Groups divergences by keyword inference and generates prioritized fix workstream specs.
Self-Improvement Cycle Pattern
┌─────────────┐
│ 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
▼
DONEReal-World Results
Used for amplihack-rs migration validation (rysweet/amplihack-rs#25):
- 118/118 comparison tests across 12 tiers
- 619/619 hook golden file tests
- 9/9 shadow harness cases
- 5 Python bugs discovered and fixed
- 1 recipe orchestrator bug discovered and fixed
- Full launcher behavioral match achieved
Changelog [LEVEL 3]
Version 1.2.0 (2026-03-11)
- NEW: Level 4 - A/B Comparison Harness & Self-Improving Audit
- Generic
ab_comparison_harness.pyfor any side-by-side CLI comparison
(migration parity, A/B testing, feature flags, version regression, canary)
- Generic
ab_audit_cycle.pyself-improvement loop SCENARIO_FORMAT.mdYAML specification- Supports
--a/--bflags (also--legacy/--candidatefor backward compat) - Example scenario file
- Extracted from amplihack-rs parity validation (118/118 tests)
Version 1.1.0 (2026-01-29)
- NEW: Level 4 - Shadow Environment Integration
- Added complete shadow testing workflow patterns
- Integration examples for Amplifier native and standalone CLI
- Multi-repo integration test patterns
- Web app testing in shadow environments
- Complete workflow example for library change validation
- References to shadow-testing skill for deep-dive documentation
Version 1.0.0 (2025-11-16)
- Initial skill release
- Support for CLI, TUI, Web, and Electron applications
- 15 complete working examples
- Progressive disclosure levels (1, 2, 3)
- Embedded gadugi-agentic-test framework documentation (v0.1.0)
- Freshness check script for version monitoring
- Full integration with amplihack philosophy
- Comprehensive troubleshooting guide
- Action reference catalog
---
Remember: Outside-in tests verify WHAT your application does, not HOW it does it. Focus on user-visible behavior, and your tests will remain stable across refactorings while providing meaningful validation of critical workflows.
Start at Level 1 with simple smoke tests, and progressively add complexity only when needed. The framework's AI agents handle the hard parts - you just describe what should happen.
# Level 1: Basic CLI Calculator Test
# This is a simple outside-in test that verifies a CLI calculator can perform basic arithmetic
# operations without knowing anything about its internal implementation.
scenario:
name: "CLI Calculator - Basic Arithmetic Operations"
description: |
Verifies that a CLI calculator application can perform addition, subtraction,
multiplication, and division operations correctly from a user's perspective.
type: cli
# Complexity level indicator
level: 1
# Test categories
tags: [cli, smoke, basic, arithmetic]
# What must be true before this test runs
prerequisites:
- "./calculator binary exists and is executable"
- "Calculator supports interactive mode"
# The test steps execute sequentially
steps:
# Step 1: Launch the calculator application
- action: launch
target: "./calculator"
args: ["--interactive"]
description: "Start calculator in interactive mode"
timeout: 5s
# Step 2: Wait for application to be ready
- action: wait_for_output
contains: "Calculator ready"
timeout: 3s
description: "Wait for startup message"
# Step 3: Test addition
- action: send_input
value: "add 5 3\n"
description: "Send addition command: 5 + 3"
- action: verify_output
contains: "Result: 8"
timeout: 2s
description: "Verify addition result is correct"
# Step 4: Test subtraction
- action: send_input
value: "subtract 10 4\n"
description: "Send subtraction command: 10 - 4"
- action: verify_output
contains: "Result: 6"
timeout: 2s
description: "Verify subtraction result is correct"
# Step 5: Test multiplication
- action: send_input
value: "multiply 7 6\n"
description: "Send multiplication command: 7 * 6"
- action: verify_output
contains: "Result: 42"
timeout: 2s
description: "Verify multiplication result is correct"
# Step 6: Test division
- action: send_input
value: "divide 20 4\n"
description: "Send division command: 20 / 4"
- action: verify_output
contains: "Result: 5"
timeout: 2s
description: "Verify division result is correct"
# Step 7: Exit gracefully
- action: send_input
value: "exit\n"
description: "Send exit command"
# Step 8: Verify clean exit
- action: verify_exit_code
expected: 0
description: "Application should exit with code 0"
# Cleanup runs even if test fails
cleanup:
- action: stop_application
force: true
description: "Ensure calculator process is terminated"
# Expected Output:
# ✓ Scenario: CLI Calculator - Basic Arithmetic Operations
# ✓ Step 1: Launched ./calculator --interactive
# ✓ Step 2: Output contains "Calculator ready"
# ✓ Step 3: Sent input "add 5 3"
# ✓ Step 4: Output contains "Result: 8"
# ✓ Step 5: Sent input "subtract 10 4"
# ✓ Step 6: Output contains "Result: 6"
# ✓ Step 7: Sent input "multiply 7 6"
# ✓ Step 8: Output contains "Result: 42"
# ✓ Step 9: Sent input "divide 20 4"
# ✓ Step 10: Output contains "Result: 5"
# ✓ Step 11: Sent input "exit"
# ✓ Step 12: Exit code is 0
#
# PASSED (12/12 steps successful)
# Evidence saved to: ./evidence/cli-calculator-basic-20250116-093045/
# How to Run:
# gadugi-agentic-test run examples/cli/calculator-basic.yaml
# Key Learning Points:
# 1. Outside-in tests don't know about Calculator class internals
# 2. Tests verify user-visible behavior (output text)
# 3. Each operation is verified independently
# 4. Cleanup ensures process termination even on failure
# 5. Timeouts prevent hanging on slow operations
# Level 2: CLI Error Handling Test
# This test verifies that a CLI application properly handles errors and provides
# helpful error messages without crashing or entering an invalid state.
scenario:
name: "CLI Application - Error Handling and Recovery"
description: |
Verifies that CLI application handles invalid input gracefully, provides
clear error messages, and allows user to recover and continue using the application.
type: cli
# Complexity level
level: 2
# Test categories
tags: [cli, error-handling, resilience, intermediate]
prerequisites:
- "./myapp binary exists and is executable"
- "Application supports interactive mode with error recovery"
# Environment variables for this test
environment:
variables:
LOG_LEVEL: "debug"
ERROR_MODE: "verbose"
steps:
# Launch application
- action: launch
target: "./myapp"
args: ["--interactive", "--mode=strict"]
description: "Start application in strict mode for error testing"
timeout: 5s
# Wait for prompt
- action: wait_for_output
contains: ">"
timeout: 3s
description: "Wait for command prompt"
# Test Case 1: Invalid command
- action: send_input
value: "invalid_command\n"
description: "Send unknown command"
- action: verify_output
contains: "Error: Unknown command 'invalid_command'"
timeout: 2s
description: "Should show clear error message"
# Verify application is still responsive
- action: verify_output
contains: ">"
description: "Should return to prompt after error"
# Test Case 2: Missing required argument
- action: send_input
value: "process\n"
description: "Send command without required argument"
- action: verify_output
matches: "Error:.*(missing|required).*argument"
case_sensitive: false
timeout: 2s
description: "Should indicate missing argument"
# Test Case 3: Invalid argument type
- action: send_input
value: "calculate abc\n"
description: "Send non-numeric value where number expected"
- action: verify_output
contains: "Error: Invalid input type"
timeout: 2s
description: "Should report type mismatch"
# Test Case 4: Out of range value
- action: send_input
value: "set_limit 99999999999\n"
description: "Send value exceeding valid range"
- action: verify_output
matches: "Error:.*(range|limit|maximum)"
case_sensitive: false
timeout: 2s
description: "Should indicate value is out of range"
# Test Case 5: Verify help still works after errors
- action: send_input
value: "help\n"
description: "Request help after multiple errors"
- action: verify_output
contains: "Available commands:"
timeout: 2s
description: "Help should still be accessible"
# Test Case 6: Verify valid command works after errors
- action: send_input
value: "status\n"
description: "Execute valid command to confirm recovery"
- action: verify_output
contains: "Status: OK"
timeout: 2s
description: "Valid commands should work after errors"
# Test Case 7: Graceful exit after errors
- action: send_input
value: "exit\n"
description: "Exit application"
- action: verify_exit_code
expected: 0
description: "Should exit cleanly even after errors"
# Capture all output for debugging
cleanup:
- action: capture_output
save_as: "error-handling-full-output.txt"
description: "Save complete session output"
- action: stop_application
force: false
description: "Allow graceful shutdown"
# Expected Behavior:
# - Application handles all error cases without crashing
# - Each error produces a clear, actionable message
# - Application returns to ready state after each error
# - Valid commands work correctly after errors
# - Application exits cleanly
# Run Command:
# gadugi-agentic-test run examples/cli/cli-error-handling.yaml --verbose
# Key Learning Points (Level 2):
# 1. Use regex patterns (matches:) for flexible error message checking
# 2. Verify application state after errors (prompt returns)
# 3. Test recovery by executing valid commands after errors
# 4. Environment variables can configure application behavior
# 5. Capture full output for debugging complex scenarios
# 6. Case-insensitive matching handles variations in error messages
# Anti-Pattern Example:
# Don't do this (too specific, brittle):
# - action: verify_output
# contains: "Error: Command 'invalid_command' not found. Did you mean 'validate'?"
#
# Do this instead (flexible):
# - action: verify_output
# matches: "Error:.*not found"
# Level 2: CLI Interactive Session Test
# This test verifies a multi-turn interactive CLI session with state management,
# demonstrating how to test complex conversational interfaces.
scenario:
name: "CLI Interactive Session - State Management"
description: |
Verifies CLI application maintains state across multiple commands in an
interactive session, including configuration, data manipulation, and query operations.
type: cli
level: 2
tags: [cli, interactive, stateful, session, intermediate]
prerequisites:
- "./data-tool binary exists"
- "Empty database state (no existing data)"
# Variables used throughout the test
variables:
dataset_name: "test_dataset"
initial_value: 100
updated_value: 250
steps:
# Initialize session
- action: launch
target: "./data-tool"
args: ["--interactive"]
description: "Launch data tool in interactive mode"
timeout: 5s
- action: wait_for_output
contains: "data-tool>"
timeout: 3s
description: "Wait for command prompt"
# Phase 1: Configuration
- action: send_input
value: "config set log_level debug\n"
description: "Configure logging level"
- action: verify_output
contains: "Configuration updated: log_level = debug"
timeout: 2s
- action: send_input
value: "config show\n"
description: "Verify configuration was saved"
- action: verify_output
contains: "log_level: debug"
timeout: 2s
description: "Configuration should persist"
# Phase 2: Data Creation
- action: send_input
value: "create dataset ${dataset_name}\n"
description: "Create new dataset using variable"
- action: verify_output
contains: "Dataset '${dataset_name}' created"
timeout: 2s
- action: send_input
value: "list datasets\n"
description: "List all datasets"
- action: verify_output
contains: "${dataset_name}"
timeout: 2s
description: "New dataset should appear in list"
# Phase 3: Data Manipulation
- action: send_input
value: "use ${dataset_name}\n"
description: "Switch to new dataset context"
- action: verify_output
contains: "Now using dataset: ${dataset_name}"
timeout: 2s
# Insert initial value
- action: send_input
value: "insert key1 ${initial_value}\n"
description: "Insert first key-value pair"
- action: verify_output
contains: "Inserted: key1 = ${initial_value}"
timeout: 2s
# Insert multiple values
- action: send_input
value: "insert key2 200\n"
description: "Insert second key-value pair"
- action: verify_output
contains: "Inserted: key2 = 200"
timeout: 2s
- action: send_input
value: "insert key3 300\n"
description: "Insert third key-value pair"
- action: verify_output
contains: "Inserted: key3 = 300"
timeout: 2s
# Phase 4: Query Operations
- action: send_input
value: "get key1\n"
description: "Retrieve first value"
- action: verify_output
contains: "key1 = ${initial_value}"
timeout: 2s
description: "Should return originally inserted value"
- action: send_input
value: "count\n"
description: "Count total entries"
- action: verify_output
contains: "Total entries: 3"
timeout: 2s
description: "Should count all inserted entries"
# Phase 5: Update Operation
- action: send_input
value: "update key1 ${updated_value}\n"
description: "Update first value"
- action: verify_output
contains: "Updated: key1 = ${updated_value}"
timeout: 2s
# Verify update persisted
- action: send_input
value: "get key1\n"
description: "Retrieve updated value"
- action: verify_output
contains: "key1 = ${updated_value}"
timeout: 2s
description: "Should return updated value, not original"
# Phase 6: Aggregation
- action: send_input
value: "sum\n"
description: "Calculate sum of all values"
- action: verify_output
contains: "Sum: 750"
timeout: 2s
description: "Should sum updated_value(250) + 200 + 300"
# Phase 7: History and Undo (advanced state management)
- action: send_input
value: "history\n"
description: "Show command history"
- action: verify_output
contains: "insert key1"
timeout: 2s
description: "History should include previous commands"
# Phase 8: Session info
- action: send_input
value: "session info\n"
description: "Display session information"
- action: verify_output
contains: "Active dataset: ${dataset_name}"
timeout: 2s
description: "Should show current context"
- action: verify_output
matches: "Commands executed: \\d+"
timeout: 2s
description: "Should track command count"
# Phase 9: Cleanup and exit
- action: send_input
value: "delete dataset ${dataset_name}\n"
description: "Clean up test dataset"
- action: verify_output
contains: "Dataset '${dataset_name}' deleted"
timeout: 2s
- action: send_input
value: "exit\n"
description: "Exit session"
- action: verify_exit_code
expected: 0
cleanup:
- action: capture_output
save_as: "interactive-session.txt"
description: "Save full session transcript"
# Expected Evidence:
# The test generates a complete session transcript showing:
# - Configuration changes
# - Dataset creation and selection
# - Multiple data insertions
# - Query operations returning correct values
# - Update operations persisting
# - Aggregate calculations
# - Command history
# - Session state information
# Run Command:
# gadugi-agentic-test run examples/cli/cli-interactive-session.yaml
# Key Learning Points (Level 2):
# 1. Variables (${var}) enable reusable, maintainable tests
# 2. Tests can verify state persists across multiple operations
# 3. Phase-based organization (comments) improves readability
# 4. Verify both operations and their side effects
# 5. Test creates and cleans up its own data
# 6. Session transcripts provide complete audit trail
# Testing Strategy:
# This test follows the pattern:
# 1. Setup (configuration)
# 2. Create (data)
# 3. Read (queries)
# 4. Update (modifications)
# 5. Verify (state checks)
# 6. Cleanup (teardown)
# Maintenance Tips:
# - Update variables at top to change test data
# - Add new operations as new phases
# - Keep phases independent where possible
# - Document expected calculations (sum example)
# Level 3: Custom Comprehension Agent
# This test demonstrates how to create domain-specific comprehension logic
# for specialized validation that goes beyond simple text matching.
scenario:
name: "Custom Agent - Financial Dashboard Validation"
description: |
Uses a custom comprehension agent with domain-specific knowledge to validate
financial dashboard data for correctness, consistency, and proper formatting.
type: web
level: 3
tags: [custom-agent, comprehension, domain-specific, advanced]
prerequisites:
- "Financial dashboard running at http://localhost:3000"
- "Dashboard has sample financial data loaded"
- "OpenAI API key available for custom agent"
# Define custom comprehension agent behavior
comprehension_agent:
model: "gpt-4"
temperature: 0.1 # Low temperature for consistent validation
# System prompt defines validation rules
system_prompt: |
You are a financial data validator specialized in dashboard validation.
Your role is to verify that financial data is correctly formatted, internally
consistent, and follows financial reporting standards.
Validation Rules:
1. Monetary values MUST use currency symbols ($, €, £, etc.)
2. Amounts >= $1,000 MUST include comma separators ($1,234.56)
3. Percentages MUST include % symbol (e.g., 15.5%)
4. Dates MUST be in MM/DD/YYYY or YYYY-MM-DD format
5. Negative values MUST be displayed in red or with minus sign
6. Charts MUST have consistent data (no impossible values)
7. Totals MUST sum correctly (verify arithmetic)
8. Year-over-year changes MUST be mathematically correct
For each verification request:
- Extract relevant numbers and check formatting
- Verify mathematical consistency
- Check for impossible values (negative revenue growth shown as positive, etc.)
- Confirm visual indicators (colors, symbols) match data semantics
Respond with:
- PASS if all validations succeed
- FAIL with specific reason if any validation fails
- List each validation check performed
# Example validations to train the agent
examples:
- input: |
Total Revenue: 45000
Growth: +15%
output: |
FAIL - Revenue formatting invalid
Issues:
1. Missing currency symbol ($)
2. Missing comma separator (should be $45,000)
Correct format: Total Revenue: $45,000
- input: |
Total Revenue: $45,000.00
Growth: +15%
Previous: $39,130.43
output: |
PASS - All validations successful
Checks performed:
1. ✓ Currency symbol present
2. ✓ Comma separator correct
3. ✓ Percentage format correct
4. ✓ Math verification: $39,130.43 * 1.15 = $45,000.00 (correct)
- input: |
Profit Margin: -5.2
Color: black text
output: |
FAIL - Visual indicator mismatch
Issues:
1. Negative value should be displayed in red
2. Missing % symbol
Correct: Profit Margin: -5.2% (in red text)
steps:
# Navigate to dashboard
- action: navigate
url: "http://localhost:3000/financial-dashboard"
wait_for_load: true
- action: wait_for_element
selector: ".dashboard-loaded"
timeout: 10s
# Test Case 1: Validate Revenue Widget with Custom Agent
- action: verify_element
selector: ".widget-revenue"
use_custom_comprehension: true
description: "Custom agent validates revenue formatting and consistency"
# The agent will:
# - Check currency formatting
# - Verify comma separators
# - Validate growth percentage
# - Check arithmetic consistency
# Test Case 2: Validate Profit Widget
- action: verify_element
selector: ".widget-profit"
use_custom_comprehension: true
description: "Validate profit metrics with custom logic"
# Test Case 3: Validate Quarterly Comparison Table
- action: verify_element
selector: ".quarterly-comparison"
use_custom_comprehension: true
context: |
This table shows quarterly revenue for Q1-Q4.
Verify: All quarters use consistent formatting, totals sum correctly,
and year-over-year changes are calculated correctly.
# Test Case 4: Validate Chart Data Consistency
- action: verify_element
selector: ".revenue-chart"
use_custom_comprehension: true
context: |
This chart displays monthly revenue trend.
Verify: Chart data points match table values, no negative revenue,
trend direction matches summary indicators.
# Test Case 5: Test Error Detection
# Inject known bad data (in test mode)
- action: click
selector: "button.inject-test-error"
description: "Inject formatting error for testing"
continue_on_failure: true
- action: wait_for_screen
timeout: 1s
# Custom agent should catch the error
- action: verify_element
selector: ".widget-revenue"
use_custom_comprehension: true
expected_result: "FAIL"
description: "Agent should detect injected formatting error"
# Verify agent provides specific error details
- action: verify_comprehension_output
contains:
- "Missing currency symbol"
- "Issues:"
description: "Agent should explain what's wrong"
# Reset dashboard
- action: click
selector: "button.reset-data"
continue_on_failure: true
# Test Case 6: Complex Validation - Multi-Currency
- action: navigate
url: "http://localhost:3000/global-revenue"
- action: wait_for_element
selector: ".currency-breakdown"
timeout: 5s
- action: verify_element
selector: ".currency-breakdown"
use_custom_comprehension: true
context: |
This widget shows revenue in multiple currencies (USD, EUR, GBP).
Verify: Each currency uses appropriate symbol, exchange rates are reasonable,
USD total matches sum of converted values.
# Test Case 7: Date Format Validation
- action: verify_element
selector: ".report-metadata"
use_custom_comprehension: true
context: |
Report metadata with dates.
Verify: All dates use consistent format (MM/DD/YYYY),
report date is not in future, fiscal year dates are valid.
- action: screenshot
save_as: "dashboard-validated.png"
cleanup:
- action: generate_report
include_agent_reasoning: true
description: "Generate report with custom agent's validation reasoning"
# Custom Comprehension Agent Benefits:
# Traditional Verification (Brittle):
# - action: verify_element
# selector: ".revenue"
# contains: "$45,000.00" # Breaks if value changes
# Custom Agent Verification (Robust):
# - action: verify_element
# selector: ".revenue"
# use_custom_comprehension: true
# # Agent validates:
# # - Has currency symbol? ✓
# # - Has comma separator? ✓
# # - Decimal places correct? ✓
# # - Consistent with growth %? ✓
# # → PASS (even if exact value changes)
# Run Command:
# gadugi-agentic-test run examples/custom-agents/custom-comprehension-agent.yaml --verbose
# Key Learning Points (Level 3):
# 1. Custom agents understand domain-specific rules
# 2. System prompts define validation logic
# 3. Examples train agent on expected behavior
# 4. Agents can verify complex consistency rules
# 5. More robust than brittle exact-match assertions
# 6. Agent reasoning included in test reports
# 7. Context parameter provides additional instructions
# When to Use Custom Comprehension Agents:
# ✓ Domain-specific validation (financial, medical, legal)
# ✓ Complex consistency checks (arithmetic, logic)
# ✓ Format verification (proper currency, date formatting)
# ✓ Visual semantics (colors match data meaning)
# ✓ Natural language outputs (error messages, summaries)
# When NOT to Use:
# ✗ Simple text matching (use contains/matches)
# ✗ Exact value verification (brittle, use traditional checks)
# ✗ Performance-critical tests (AI calls add latency)
# Custom Agent Configuration:
# - model: Choose appropriate AI model (GPT-4 for complex logic)
# - temperature: Low (0-0.3) for consistent validation
# - system_prompt: Define validation rules clearly
# - examples: Provide representative pass/fail cases
# - context: Per-test additional instructions
# Cost Considerations:
# - Each custom verification calls AI API
# - Use strategically for high-value validations
# - Cache agent responses when possible
# - Consider cost vs. value of robust validation
# Level 3: Custom Reporter Integration
# This test demonstrates custom reporting formats including integration with
# external systems, custom HTML templates, and automated notifications.
scenario:
name: "Custom Reporter - Comprehensive Test Reporting"
description: |
Demonstrates custom test reporting with HTML templates, metrics tracking,
external system integration, and automated notifications on test completion.
type: web
level: 3
tags: [custom-reporter, reporting, integration, advanced]
prerequisites:
- "Application running at http://localhost:3000"
- "Reporting webhook endpoint available (optional)"
- "Email service configured (optional)"
# Custom reporting configuration
reporting:
# Primary report format
format: custom
template: "./report-templates/detailed-report.html"
# Additional output formats
outputs:
- format: json
file: "test-results.json"
- format: junit
file: "junit-results.xml"
- format: html
file: "test-report.html"
# What to include in reports
include:
- screenshots
- timing_data
- network_logs
- console_logs
- video_recording
- coverage_data
# Metrics to track
metrics:
- test_duration
- page_load_times
- action_response_times
- screenshot_count
- error_count
- network_request_count
# External integrations
integrations:
# Webhook notification
- type: webhook
url: "https://hooks.example.com/test-results"
on: completion
payload:
scenario: "${scenario.name}"
status: "${result.status}"
duration: "${result.duration}"
timestamp: "${result.timestamp}"
# Slack notification
- type: slack
webhook_url: "${SLACK_WEBHOOK_URL}"
on: failure
message: |
❌ Test Failed: ${scenario.name}
Duration: ${result.duration}
Failed Step: ${result.failed_step}
See report: ${result.report_url}
# Email notification
- type: email
recipients: ["team@example.com"]
on: failure
subject: "Test Failure: ${scenario.name}"
template: "./email-templates/failure-notification.html"
# TestRail integration
- type: testrail
enabled: false
project_id: 123
suite_id: 456
run_name: "Automated Run ${timestamp}"
# Jira integration (create ticket on failure)
- type: jira
enabled: false
on: failure
project: "TEST"
issue_type: "Bug"
summary: "Test Failure: ${scenario.name}"
description: |
Automated test failed: ${scenario.name}
Failed Step: ${result.failed_step}
Error: ${result.error_message}
Report: ${result.report_url}
Screenshots: ${result.screenshot_urls}
# Report customization
custom_data:
build_number: "${BUILD_NUMBER}"
commit_sha: "${GIT_COMMIT}"
branch: "${GIT_BRANCH}"
environment: "staging"
tester: "automated"
steps:
# Test Case 1: Basic Page Load with Timing
- action: navigate
url: "http://localhost:3000"
measure_timing: true
description: "Load homepage and measure timing"
- action: wait_for_element
selector: ".page-loaded"
timeout: 10s
- action: screenshot
save_as: "01-homepage.png"
annotate:
title: "Homepage Load"
timestamp: true
# Test Case 2: User Interaction Flow
- action: click
selector: "button.get-started"
measure_timing: true
- action: wait_for_element
selector: ".onboarding"
timeout: 5s
- action: screenshot
save_as: "02-onboarding.png"
# Test Case 3: Form Submission with Network Monitoring
- action: start_network_monitoring
description: "Monitor network requests during form submission"
- action: type
selector: "input[name='email']"
value: "test@example.com"
- action: click
selector: "button[type='submit']"
- action: wait_for_element
selector: ".success-message"
timeout: 10s
- action: stop_network_monitoring
description: "Stop monitoring and capture network data"
# Test Case 4: Performance Metrics
- action: measure_performance
metrics:
- first_contentful_paint
- largest_contentful_paint
- cumulative_layout_shift
- time_to_interactive
# Test Case 5: Intentional Failure for Demo
- action: verify_element
selector: ".nonexistent-element"
exists: true
continue_on_failure: true
description: "This will fail to demonstrate failure reporting"
# Final screenshot
- action: screenshot
save_as: "03-final-state.png"
full_page: true
# Cleanup and report generation
cleanup:
# Generate custom HTML report
- action: generate_report
template: detailed
include_traces: true
description: "Generate comprehensive HTML report"
# Export metrics to database
- action: export_metrics
destination: "postgres://metrics-db"
table: "test_results"
continue_on_failure: true
# Upload artifacts to S3
- action: upload_artifacts
destination: "s3://test-reports/${date}/"
files:
- "*.png"
- "*.json"
- "*.html"
continue_on_failure: true
# Custom Report Template Structure (detailed-report.html):
# <!DOCTYPE html>
# <html>
# <head>
# <title>Test Report: {{scenario.name}}</title>
# <style>
# /* Custom styling */
# </style>
# </head>
# <body>
# <header>
# <h1>{{scenario.name}}</h1>
# <div class="metadata">
# <span>Status: {{result.status}}</span>
# <span>Duration: {{result.duration}}s</span>
# <span>Timestamp: {{result.timestamp}}</span>
# </div>
# </header>
#
# <section class="summary">
# <h2>Summary</h2>
# <ul>
# <li>Total Steps: {{steps.total}}</li>
# <li>Passed: {{steps.passed}}</li>
# <li>Failed: {{steps.failed}}</li>
# <li>Skipped: {{steps.skipped}}</li>
# </ul>
# </section>
#
# <section class="metrics">
# <h2>Performance Metrics</h2>
# <table>
# <tr><th>Metric</th><th>Value</th></tr>
# {{#each metrics}}
# <tr><td>{{name}}</td><td>{{value}}</td></tr>
# {{/each}}
# </table>
# </section>
#
# <section class="steps">
# <h2>Test Steps</h2>
# {{#each steps}}
# <div class="step {{status}}">
# <h3>Step {{number}}: {{action}}</h3>
# <p>{{description}}</p>
# <div class="timing">Duration: {{duration}}ms</div>
# {{#if screenshot}}
# <img src="{{screenshot}}" alt="Screenshot">
# {{/if}}
# {{#if error}}
# <div class="error">{{error}}</div>
# {{/if}}
# </div>
# {{/each}}
# </section>
#
# <section class="network">
# <h2>Network Activity</h2>
# {{#each network_requests}}
# <div class="request">
# <span class="method">{{method}}</span>
# <span class="url">{{url}}</span>
# <span class="status">{{status}}</span>
# <span class="duration">{{duration}}ms</span>
# </div>
# {{/each}}
# </section>
#
# <section class="console">
# <h2>Console Logs</h2>
# <pre>{{console_logs}}</pre>
# </section>
# </body>
# </html>
# Run Command:
# gadugi-agentic-test run examples/custom-agents/custom-reporter-integration.yaml
# With environment variables:
# SLACK_WEBHOOK_URL=https://hooks.slack.com/... \
# BUILD_NUMBER=123 \
# GIT_COMMIT=abc123 \
# gadugi-agentic-test run examples/custom-agents/custom-reporter-integration.yaml
# Key Learning Points (Level 3):
# 1. Custom report templates for branded/detailed reports
# 2. Multiple output formats (JSON, JUnit, HTML)
# 3. External system integrations (Slack, email, webhooks)
# 4. Performance metrics tracking and reporting
# 5. Network monitoring and request logging
# 6. Artifact upload to cloud storage
# 7. Database integration for metrics
# 8. Conditional notifications (on failure, on completion)
# Report Outputs Generated:
# - test-report.html (custom template with all details)
# - test-results.json (machine-readable results)
# - junit-results.xml (for CI/CD integration)
# - Screenshots (01-homepage.png, 02-onboarding.png, etc.)
# - Network logs (HTTP requests/responses)
# - Console logs (browser console output)
# - Performance metrics (timing data)
# Integration Patterns:
# 1. Continuous Integration:
# - JUnit XML for Jenkins/GitHub Actions/GitLab CI
# - Exit code for build pass/fail
# - Artifacts uploaded to CI storage
# 2. Test Management:
# - TestRail integration for test case tracking
# - Jira integration for bug creation
# - Custom webhooks for proprietary systems
# 3. Notifications:
# - Slack for team alerts
# - Email for stakeholder reports
# - PagerDuty for critical failures (not shown)
# 4. Metrics & Analytics:
# - Database export for trending
# - Grafana dashboards (query database)
# - Custom analytics platforms
# Template Variables Available:
# - ${scenario.name} - Test scenario name
# - ${result.status} - PASSED/FAILED/SKIPPED
# - ${result.duration} - Total duration in seconds
# - ${result.timestamp} - ISO timestamp
# - ${result.failed_step} - First failed step
# - ${result.error_message} - Error details
# - ${steps.total} - Total step count
# - ${steps.passed} - Passed step count
# - ${metrics.*} - Any collected metric
# - ${BUILD_NUMBER} - From environment
# - ${GIT_COMMIT} - From environment
# Best Practices:
# - Keep reports self-contained (embed screenshots)
# - Include context (build number, commit, branch)
# - Add timing data for performance tracking
# - Use conditional notifications (don't spam)
# - Store reports in versioned storage
# - Include logs for debugging failures
# - Generate multiple formats for different audiences
# Level 3: Electron IPC Testing
# This advanced test verifies Inter-Process Communication between the main process
# and renderer processes in an Electron application.
scenario:
name: "Electron IPC - Inter-Process Communication Testing"
description: |
Verifies IPC communication between main and renderer processes, including
request/response patterns, event broadcasting, and data serialization.
type: electron
level: 3
tags: [electron, ipc, advanced, main-process, renderer-process]
prerequisites:
- "./dist/advanced-app executable exists"
- "Application implements IPC channels for testing"
steps:
- action: launch
target: "./dist/advanced-app"
wait_for_window: true
timeout: 10s
# Test Case 1: Simple Request-Response IPC
- action: ipc_send
channel: "get-system-info"
description: "Request system information from main process"
- action: ipc_expect
channel: "system-info-reply"
timeout: 3s
description: "Wait for main process response"
- action: verify_ipc_payload
contains:
platform: "darwin"
arch: "x64"
description: "Verify system info structure"
# Test Case 2: IPC with Data Payload
- action: ipc_send
channel: "calculate"
data:
operation: "multiply"
values: [5, 7]
- action: ipc_expect
channel: "calculate-result"
timeout: 2s
- action: verify_ipc_payload
equals:
result: 35
operation: "multiply"
# Test Case 3: File System Operations via IPC
- action: ipc_send
channel: "read-file"
data:
path: "./test-data.json"
- action: ipc_expect
channel: "file-content"
timeout: 5s
- action: verify_ipc_payload
contains:
success: true
data: "{}" # Some JSON content
# Test Case 4: Event Broadcasting (Main → Renderer)
- action: wait_for_element
selector: ".status-indicator"
timeout: 3s
# Trigger background task in main process
- action: click
selector: "button.start-background-task"
- action: ipc_expect
channel: "task-progress"
timeout: 10s
description: "Wait for progress updates from main process"
- action: verify_ipc_payload
matches:
progress: "\\d+"
status: "(running|completed)"
- action: wait_for_element
selector: ".task-complete"
timeout: 15s
# Test Case 5: Error Handling in IPC
- action: ipc_send
channel: "invalid-operation"
data:
action: "nonexistent"
- action: ipc_expect
channel: "error"
timeout: 3s
- action: verify_ipc_payload
contains:
error: true
message: "Unknown operation"
# Test Case 6: Multi-Window IPC
- action: menu_click
path: ["Window", "New Window"]
- action: wait_for_window
count: 2
timeout: 5s
# Send IPC from first window
- action: window_action
window: 1
type: focus
- action: ipc_send
channel: "broadcast-message"
data:
message: "Hello from window 1"
# Verify received in second window
- action: window_action
window: 2
type: focus
- action: wait_for_element
selector: ".broadcast-message"
contains: "Hello from window 1"
timeout: 5s
# Test Case 7: Native Dialog via IPC
- action: ipc_send
channel: "show-open-dialog"
data:
title: "Select File"
filters: [{ name: "Text Files", extensions: ["txt"] }]
# Simulate dialog interaction (in test mode)
- action: dialog_action
type: open_file
select: "./test-file.txt"
- action: ipc_expect
channel: "dialog-result"
timeout: 5s
- action: verify_ipc_payload
contains:
filePaths: ["./test-file.txt"]
# Cleanup
- action: menu_click
path: ["File", "Quit"]
- action: verify_exit_code
expected: 0
cleanup:
- action: stop_application
force: false
# IPC Communication Patterns:
# Main Process Renderer Process
# ┌──────────────────┐ ┌──────────────────┐
# │ │ │ │
# │ ipcMain.on() │<──req──── │ ipcRenderer │
# │ │ │ .send() │
# │ do work... │ │ │
# │ │ │ ipcRenderer │
# │ win.webContents│───resp───> │ .on() │
# │ .send() │ │ │
# └──────────────────┘ └──────────────────┘
# Run Command:
# gadugi-agentic-test run examples/electron/electron-ipc-testing.yaml --verbose
# Key Learning Points (Level 3):
# 1. ipc_send triggers IPC from renderer
# 2. ipc_expect waits for IPC events
# 3. verify_ipc_payload validates message content
# 4. IPC can be request-response or broadcast
# 5. Error handling in IPC channels
# 6. Cross-window IPC communication
# 7. Native dialog integration via IPC
# Common IPC Channels to Test:
# - get-app-version: Application metadata
# - file-operations: Read, write, delete files
# - system-info: OS, platform, architecture
# - database-query: Database operations
# - background-tasks: Long-running operations
# - window-control: Manage windows
# - native-dialogs: Open, save, message dialogs
# - notifications: System notifications
# IPC Testing Best Practices:
# - Test both directions (renderer → main, main → renderer)
# - Verify payload structure and types
# - Test error conditions
# - Test timeout handling
# - Verify cross-window broadcasting
# - Test serialization of complex data
# - Verify async operation completion
# Level 2: Electron Menu Testing
# This test comprehensively verifies application menu functionality including
# keyboard shortcuts, menu state, and menu-triggered actions.
scenario:
name: "Electron Menus - Comprehensive Menu Testing"
description: |
Verifies all menu items, keyboard shortcuts, menu states (enabled/disabled),
and menu-triggered actions work correctly.
type: electron
level: 2
tags: [electron, menus, keyboard-shortcuts, intermediate]
prerequisites:
- "./dist/text-editor executable exists"
- "Application has comprehensive menu structure"
steps:
- action: launch
target: "./dist/text-editor"
wait_for_window: true
timeout: 10s
# Test File Menu
- action: menu_click
path: ["File", "New"]
description: "File > New"
- action: verify_element
selector: ".editor"
exists: true
# Test keyboard shortcut (Cmd/Ctrl+N)
- action: send_keypress
value: "ctrl+n"
description: "Test New file keyboard shortcut"
- action: verify_window
count: 1
description: "Should create new tab, not new window"
# Test Edit Menu
- action: type
selector: ".editor"
value: "Sample text for testing"
- action: menu_click
path: ["Edit", "Select All"]
- action: send_keypress
value: "ctrl+c"
description: "Copy selected text"
- action: menu_click
path: ["Edit", "Paste"]
- action: verify_element
selector: ".editor"
contains: "Sample text for testing"
# Test View Menu
- action: menu_click
path: ["View", "Zoom In"]
- action: wait_for_screen
timeout: 0.5s
- action: menu_click
path: ["View", "Zoom Out"]
- action: menu_click
path: ["View", "Toggle Full Screen"]
- action: verify_window
fullscreen: true
timeout: 2s
- action: send_keypress
value: "f11"
description: "Exit fullscreen via F11"
- action: verify_window
fullscreen: false
timeout: 2s
# Test disabled menu items
- action: menu_click
path: ["Edit", "Undo"]
description: "Should be enabled after typing"
- action: menu_click
path: ["Edit", "Redo"]
continue_on_failure: true
description: "May be disabled if nothing to redo"
# Test Help Menu
- action: menu_click
path: ["Help", "Documentation"]
- action: wait_for_element
selector: ".help-window"
timeout: 3s
continue_on_failure: true
- action: menu_click
path: ["File", "Quit"]
- action: verify_exit_code
expected: 0
cleanup:
- action: stop_application
force: false
# Run Command:
# gadugi-agentic-test run examples/electron/electron-menu-testing.yaml
# Level 2: Electron Multi-Window Coordination
# This test verifies coordination between multiple windows, data sharing,
# and window management in a multi-window Electron application.
scenario:
name: "Electron Multi-Window - Window Coordination"
description: |
Verifies Electron application can manage multiple windows, coordinate data
between them, and handle window lifecycle correctly.
type: electron
level: 2
tags: [electron, multi-window, coordination, intermediate]
prerequisites:
- "./dist/chat-app executable exists"
- "Application supports multiple chat windows"
variables:
chat_room_1: "General"
chat_room_2: "Development"
message_1: "Hello from window 1"
message_2: "Reply from window 2"
steps:
# Launch main application window
- action: launch
target: "./dist/chat-app"
wait_for_window: true
timeout: 10s
description: "Launch main chat application"
- action: verify_window
title: "Chat Application"
count: 1
- action: screenshot
save_as: "01-main-window.png"
# Test Case 1: Open Second Chat Window
- action: menu_click
path: ["Window", "New Chat"]
description: "Open new chat window via menu"
- action: wait_for_window
count: 2
timeout: 5s
description: "Wait for second window to appear"
- action: verify_window
count: 2
description: "Should now have 2 windows"
# Test Case 2: Focus on First Window
- action: window_action
window: 1
type: focus
description: "Focus on first window (0-indexed)"
- action: verify_window
window: 1
focused: true
description: "First window should be focused"
- action: wait_for_element
selector: ".chat-room-list"
timeout: 3s
# Join first chat room in window 1
- action: click
text: "${chat_room_1}"
description: "Join ${chat_room_1} room"
- action: wait_for_element
selector: ".chat-active"
contains: "${chat_room_1}"
timeout: 3s
- action: type
selector: ".message-input"
value: "${message_1}"
description: "Type message in window 1"
- action: click
selector: "button.send-message"
description: "Send message"
- action: verify_element
selector: ".message-item:last-child"
contains: "${message_1}"
description: "Message should appear in chat"
- action: screenshot
save_as: "02-window1-message-sent.png"
# Test Case 3: Switch to Second Window
- action: window_action
window: 2
type: focus
description: "Focus on second window"
- action: verify_window
window: 2
focused: true
- action: wait_for_element
selector: ".chat-room-list"
timeout: 3s
# Join SAME chat room in window 2
- action: click
text: "${chat_room_1}"
description: "Join ${chat_room_1} room in window 2"
- action: wait_for_element
selector: ".chat-active"
contains: "${chat_room_1}"
timeout: 3s
# Test Case 4: Verify Message Sync Between Windows
- action: wait_for_element
selector: ".message-item"
contains: "${message_1}"
timeout: 5s
description: "Message from window 1 should appear in window 2"
- action: screenshot
save_as: "03-window2-message-synced.png"
# Test Case 5: Send Message from Window 2
- action: type
selector: ".message-input"
value: "${message_2}"
- action: click
selector: "button.send-message"
- action: wait_for_element
selector: ".message-item:last-child"
contains: "${message_2}"
timeout: 3s
- action: screenshot
save_as: "04-window2-message-sent.png"
# Test Case 6: Verify Sync Back to Window 1
- action: window_action
window: 1
type: focus
description: "Switch back to window 1"
- action: wait_for_element
selector: ".message-item"
contains: "${message_2}"
timeout: 5s
description: "Message from window 2 should sync to window 1"
- action: screenshot
save_as: "05-window1-received-reply.png"
# Test Case 7: Open Third Window (Different Chat Room)
- action: menu_click
path: ["Window", "New Chat"]
- action: wait_for_window
count: 3
timeout: 5s
- action: window_action
window: 3
type: focus
- action: click
text: "${chat_room_2}"
description: "Join different chat room in window 3"
- action: wait_for_element
selector: ".chat-active"
contains: "${chat_room_2}"
timeout: 3s
# Verify independent chat state
- action: verify_element
selector: ".message-item"
contains: "${message_1}"
exists: false
description: "Messages from other room shouldn't appear here"
# Test Case 8: Cascade Windows Arrangement
- action: menu_click
path: ["Window", "Cascade"]
description: "Arrange windows in cascade layout"
- action: wait_for_screen
timeout: 1s
description: "Wait for window rearrangement"
# Verify all windows still exist
- action: verify_window
count: 3
description: "All 3 windows should still exist"
# Test Case 9: Close One Window
- action: window_action
window: 3
type: close
description: "Close third window"
- action: wait_for_window
count: 2
timeout: 3s
description: "Should have 2 windows remaining"
# Test Case 10: Verify Other Windows Unaffected
- action: window_action
window: 1
action: focus
- action: verify_element
selector: ".chat-active"
contains: "${chat_room_1}"
description: "Window 1 should still be in ${chat_room_1}"
- action: verify_element
selector: ".message-item"
contains: "${message_1}"
description: "Messages should still be present"
# Test Case 11: Close All Windows Via Menu
- action: menu_click
path: ["Window", "Close All"]
description: "Close all chat windows"
- action: wait_for_window
count: 0
timeout: 5s
- action: verify_exit_code
expected: 0
cleanup:
- action: stop_application
force: false
# Multi-Window Coordination Patterns:
# Window 1 (General) Window 2 (General) Window 3 (Development)
# ┌────────────────┐ ┌────────────────┐ ┌────────────────┐
# │ General ✓ │ │ General ✓ │ │ Development ✓ │
# ├────────────────┤ ├────────────────┤ ├────────────────┤
# │ User1: Hello │ sync │ User1: Hello │ │ (different │
# │ User2: Reply │ <───────>│ User2: Reply │ │ chat room) │
# │ [________] [>] │ │ [________] [>] │ │ [________] [>] │
# └────────────────┘ └────────────────┘ └────────────────┘
# Run Command:
# gadugi-agentic-test run examples/electron/multi-window-coordination.yaml --verbose
# Key Learning Points (Level 2):
# 1. window_action with window parameter targets specific windows
# 2. wait_for_window with count waits for window creation/closure
# 3. Data synchronization between windows can be tested
# 4. Independent window states (different chat rooms)
# 5. Window arrangement commands (cascade, tile)
# 6. Closing individual windows vs. close all
# 7. Focus management between multiple windows
# Multi-Window Testing Strategy:
# - Open multiple windows
# - Verify independent operation
# - Test data synchronization (if applicable)
# - Test window focus switching
# - Test window arrangement
# - Verify closing one doesn't affect others
# - Test close all functionality
# Common Multi-Window Patterns:
# - Chat applications (multiple conversations)
# - Code editors (multiple files)
# - Image editors (multiple documents)
# - Browser-like apps (multiple tabs/windows)
# - Dashboard apps (multiple views)
# Window Indexing:
# - Windows are 0-indexed: 1, 2, 3, etc.
# - Index is creation order, not Z-order
# - Closing a window doesn't renumber others
# Synchronization Testing:
# - Verify data appears in all relevant windows
# - Test real-time updates between windows
# - Verify isolation (unrelated windows don't get updates)
# - Test conflict resolution if applicable
# Level 1: Basic Electron Single Window Test
# This test verifies basic Electron application launch, window properties,
# and simple interactions in a single-window desktop application.
scenario:
name: "Electron Application - Single Window Basics"
description: |
Verifies Electron desktop application launches correctly, displays a single window
with expected properties, and handles basic menu interactions.
type: electron
level: 1
tags: [electron, desktop, single-window, basic]
prerequisites:
- "./dist/my-app executable exists (built Electron app)"
- "Application is configured for single-window mode"
steps:
# Launch Electron application
- action: launch
target: "./dist/my-app"
wait_for_window: true
timeout: 10s
description: "Start Electron application and wait for main window"
# Test Case 1: Verify Window Properties
- action: verify_window
title: "My Application"
visible: true
focused: true
description: "Main window should be visible and focused"
- action: verify_window
count: 1
description: "Should have exactly one window"
- action: verify_window
width: 800
height: 600
tolerance: 20
description: "Window should have default dimensions (±20px tolerance)"
# Take screenshot of initial state
- action: screenshot
save_as: "01-application-launched.png"
description: "Capture initial window state"
# Test Case 2: Verify Window Content (web content in Electron)
- action: wait_for_element
selector: ".app-container"
timeout: 5s
description: "Wait for main app container to render"
- action: verify_element
selector: "h1.app-title"
contains: "Welcome to My Application"
description: "Should display welcome message"
- action: verify_element
selector: "button.action-button"
count: 3
description: "Should have 3 action buttons"
# Test Case 3: Test Basic Interaction
- action: click
selector: "button.open-file"
description: "Click 'Open File' button"
- action: wait_for_element
selector: ".file-info"
timeout: 3s
description: "File info panel should appear"
- action: screenshot
save_as: "02-file-panel-opened.png"
# Test Case 4: Menu Interaction
- action: menu_click
path: ["File", "New Document"]
description: "Click File > New Document menu item"
- action: wait_for_element
selector: ".document-editor"
timeout: 3s
description: "Document editor should appear"
- action: verify_element
selector: ".document-title"
contains: "Untitled"
description: "New document should be titled 'Untitled'"
- action: screenshot
save_as: "03-new-document-created.png"
# Test Case 5: Type in Editor
- action: type
selector: ".document-editor textarea"
value: "This is a test document created by automated testing."
description: "Type test content into editor"
- action: verify_element
selector: ".document-editor textarea"
contains: "automated testing"
description: "Text should appear in editor"
- action: screenshot
save_as: "04-text-entered.png"
# Test Case 6: Test Window Controls
- action: window_action
type: minimize
description: "Minimize window"
- action: wait_for_screen
timeout: 1s
description: "Allow minimize animation"
- action: verify_window
visible: false
description: "Window should not be visible when minimized"
- action: window_action
type: restore
description: "Restore window"
- action: wait_for_screen
timeout: 1s
- action: verify_window
visible: true
focused: true
description: "Window should be visible and focused after restore"
# Test Case 7: Test Menu - View Options
- action: menu_click
path: ["View", "Toggle Sidebar"]
description: "Toggle sidebar visibility"
- action: wait_for_element
selector: ".sidebar"
disappears: true
timeout: 2s
description: "Sidebar should disappear"
- action: menu_click
path: ["View", "Toggle Sidebar"]
description: "Toggle sidebar again"
- action: wait_for_element
selector: ".sidebar"
timeout: 2s
description: "Sidebar should reappear"
# Test Case 8: Test Help Menu
- action: menu_click
path: ["Help", "About"]
description: "Open About dialog"
- action: wait_for_element
selector: ".about-dialog"
timeout: 3s
description: "About dialog should appear"
- action: verify_element
selector: ".about-dialog .version"
matches: "Version \\d+\\.\\d+\\.\\d+"
description: "Should display version number"
- action: screenshot
save_as: "05-about-dialog.png"
# Close about dialog
- action: click
selector: ".about-dialog button.close"
description: "Close about dialog"
- action: wait_for_element
selector: ".about-dialog"
disappears: true
timeout: 2s
# Test Case 9: Test Window Title Updates
- action: menu_click
path: ["File", "Save"]
description: "Attempt to save document"
- action: verify_window
title_contains: "Untitled"
description: "Window title should still contain 'Untitled' before save"
# Test Case 10: Clean Exit
- action: menu_click
path: ["File", "Close"]
description: "Close document"
# May show unsaved changes dialog
- action: click
selector: "button.dont-save"
continue_on_failure: true
description: "Click 'Don't Save' if prompted"
- action: verify_element
selector: ".document-editor"
exists: false
description: "Document editor should be closed"
# Exit application
- action: menu_click
path: ["File", "Quit"]
description: "Quit application via menu"
# Verify application closed
- action: verify_window
count: 0
timeout: 5s
description: "All windows should be closed"
- action: verify_exit_code
expected: 0
description: "Application should exit cleanly"
cleanup:
- action: stop_application
force: false
description: "Ensure application is terminated"
# Expected Application Structure:
# ┌─────────────────────────────────────────────────────┐
# │ My Application _ □ ✕ │ (Window chrome)
# ├─────────────────────────────────────────────────────┤
# │ File Edit View Help │ (Menu bar)
# ├───────┬─────────────────────────────────────────────┤
# │ Side │ Welcome to My Application │
# │ bar │ │
# │ │ [Open File] [New Doc] [Settings] │
# │ │ │
# │ │ Document Editor: │
# │ [•] │ ┌──────────────────────────────────────┐ │
# │ [•] │ │ Untitled │ │
# │ [•] │ │ │ │
# │ │ │ (Text content here) │ │
# │ │ │ │ │
# │ │ └──────────────────────────────────────┘ │
# │ │ │
# └───────┴─────────────────────────────────────────────┘
# Run Command:
# gadugi-agentic-test run examples/electron/single-window-basic.yaml
# Key Learning Points (Level 1):
# 1. launch with wait_for_window ensures app is ready
# 2. verify_window checks window state (title, visibility, count)
# 3. Electron apps combine native (menus, windows) and web (DOM) interactions
# 4. menu_click navigates application menus by path
# 5. window_action controls window state (minimize, restore, maximize)
# 6. Screenshots capture both native chrome and web content
# 7. Both native and web selectors work in Electron tests
# Electron Testing Patterns:
# - Launch and wait for window
# - Verify window properties first
# - Test menu interactions (native UI)
# - Test web content (DOM elements)
# - Test window controls (minimize, restore)
# - Test dialogs (native and custom)
# - Clean exit via menu
# Electron-Specific Actions:
# - launch: Start Electron app
# - verify_window: Check window properties
# - window_action: Control window state
# - menu_click: Navigate native menus
# - All web actions: Work on renderer content
# Common Electron App Patterns:
# - File menu: New, Open, Save, Close, Quit
# - Edit menu: Undo, Redo, Cut, Copy, Paste
# - View menu: Zoom, Fullscreen, DevTools
# - Help menu: About, Documentation, Updates
# Platform Considerations:
# - macOS: Menu bar is global (not in window)
# - Windows/Linux: Menu bar is in window
# - Use platform-agnostic menu_click (framework handles differences)
# Level 1: Basic TUI File Manager Navigation
# This test demonstrates keyboard-based navigation in a terminal user interface,
# verifying screen state after navigation actions.
scenario:
name: "TUI File Manager - Basic Navigation"
description: |
Verifies keyboard navigation in a TUI file manager application.
Tests arrow key movement, directory entry, and screen state verification.
type: tui
level: 1
tags: [tui, navigation, keyboard, basic]
prerequisites:
- "./file-manager binary exists"
- "Test directory structure exists with predictable files"
- "Terminal supports ANSI escape codes"
# Terminal configuration
environment:
terminal_size:
width: 80
height: 24
variables:
TERM: "xterm-256color"
steps:
# Launch the TUI application
- action: launch
target: "./file-manager"
args: ["--test-mode", "--path=/test-root"]
description: "Start file manager in test directory"
timeout: 5s
# Wait for initial screen render
- action: wait_for_screen
contains: "File Manager v"
timeout: 3s
description: "Wait for application header to appear"
# Verify initial state shows file list
- action: verify_screen
contains: "documents/"
description: "Should display documents directory"
- action: verify_screen
contains: "downloads/"
description: "Should display downloads directory"
- action: verify_screen
contains: "pictures/"
description: "Should display pictures directory"
# Capture initial state
- action: capture_screenshot
save_as: "initial-state.txt"
description: "Save initial directory listing"
# Test Case 1: Navigate down in list
- action: send_keypress
value: "down"
description: "Move selection down one item"
- action: verify_screen
contains: "> documents/"
description: "First item should now be selected (> indicator)"
# Move down again
- action: send_keypress
value: "down"
description: "Move selection down again"
- action: verify_screen
contains: "> downloads/"
description: "Second item should be selected"
# Move down once more
- action: send_keypress
value: "down"
description: "Move selection to third item"
- action: verify_screen
contains: "> pictures/"
description: "Third item should be selected"
# Test Case 2: Navigate up in list
- action: send_keypress
value: "up"
description: "Move selection up one item"
- action: verify_screen
contains: "> downloads/"
description: "Should return to second item"
- action: send_keypress
value: "up"
description: "Move selection up again"
- action: verify_screen
contains: "> documents/"
description: "Should return to first item"
# Test Case 3: Enter directory
- action: send_keypress
value: "enter"
description: "Enter the documents directory"
- action: wait_for_screen
contains: "documents/"
timeout: 2s
description: "Wait for directory contents to load"
# Verify we're inside the directory
- action: verify_screen
contains: "report.pdf"
description: "Should show files inside documents/"
- action: verify_screen
contains: "notes.txt"
description: "Should show additional files"
# Capture directory view
- action: capture_screenshot
save_as: "documents-directory.txt"
description: "Save documents directory view"
# Test Case 4: Navigate back to parent
- action: send_keypress
value: "backspace"
description: "Return to parent directory"
- action: wait_for_screen
contains: "downloads/"
timeout: 2s
description: "Should return to root level"
# Verify back at root
- action: verify_screen
contains: "documents/"
description: "Should see all top-level directories again"
# Test Case 5: Quick navigation with multiple keys
- action: send_keypress
value: "down"
times: 3
description: "Press down 3 times quickly"
- action: verify_screen
contains: "> pictures/"
description: "Should reach pictures directory"
# Test Case 6: Status bar verification
- action: verify_screen
matches: "\\d+ items"
description: "Status bar should show item count"
# Exit application
- action: send_keypress
value: "q"
description: "Quit application (q key)"
- action: verify_exit_code
expected: 0
description: "Should exit cleanly"
cleanup:
- action: stop_application
force: false
description: "Allow graceful shutdown"
# Expected Screen State Examples:
# Initial State:
# ┌────────────────────────────────────────────┐
# │ File Manager v1.0 /test-root │
# ├────────────────────────────────────────────┤
# │ > documents/ │
# │ downloads/ │
# │ pictures/ │
# │ │
# ├────────────────────────────────────────────┤
# │ 3 items | q: quit | enter: open │
# └────────────────────────────────────────────┘
# After navigation (down x2):
# │ documents/ │
# │ > downloads/ │
# │ pictures/ │
# Inside documents/:
# │ > report.pdf │
# │ notes.txt │
# │ spreadsheet.xlsx │
# Run Command:
# gadugi-agentic-test run examples/tui/file-manager-navigation.yaml
# Key Learning Points (Level 1):
# 1. TUI tests verify screen content, not internal state
# 2. send_keypress simulates keyboard input
# 3. verify_screen checks visible text on screen
# 4. wait_for_screen handles async screen updates
# 5. Terminal screenshots (ANSI text) provide evidence
# 6. times parameter repeats keypresses efficiently
# TUI Testing Patterns:
# - Always wait for screen updates before verification
# - Use visual indicators (>, highlighting) to verify selection
# - Capture screenshots at key states for debugging
# - Set terminal size explicitly for consistent rendering
# - Test both forward and backward navigation
# Common TUI Actions:
# - Arrow keys: "up", "down", "left", "right"
# - Special keys: "enter", "backspace", "escape", "tab"
# - Control keys: "ctrl+c", "ctrl+d", "ctrl+z"
# - Function keys: "f1", "f2", etc.
# - Text keys: Any printable character