Skip to content

Commit c847979

Browse files
author
Julien Larocque-Dupont
authored
Merge pull request #576 from homeassistant-ai/feat/uat-framework
feat: add UAT framework for agent-driven acceptance testing
2 parents dba4c8f + a02533c commit c847979

6 files changed

Lines changed: 1229 additions & 2 deletions

File tree

File renamed without changes.

.claude/skills/bat/SKILL.md

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
---
2+
name: bat
3+
description: Run bot acceptance tests to validate MCP tools work correctly from a real AI agent's perspective. Use when testing PRs, detecting regressions, or verifying tool changes end-to-end with Claude/Gemini CLIs.
4+
disable-model-invocation: true
5+
argument-hint: [scenario-description or --help]
6+
allowed-tools: Bash, Read, Write
7+
---
8+
9+
# BAT - Bot Acceptance Testing
10+
11+
Bot acceptance testing validates that MCP tools work correctly from a real AI agent's perspective. You design test scenarios dynamically, run them via `tests/uat/run_uat.py`, and evaluate results.
12+
13+
## When to Use BAT
14+
15+
- **PR validation**: Test that tool changes work correctly from an agent's perspective
16+
- **Regression detection**: Compare behavior between branches
17+
- **Integration verification**: Ensure MCP tools work end-to-end with real agent CLIs
18+
19+
## Workflow
20+
21+
1. **Analyze the change**: Read the diff, identify which tools are affected
22+
2. **Design scenario**: Generate a scenario JSON with setup/test/teardown prompts
23+
3. **Run the script**: Pipe the scenario to `python tests/uat/run_uat.py`
24+
4. **Evaluate summary**: Check `all_passed` per agent. If true, you're done.
25+
5. **Dig deeper on failure**: Read `results_file` for full output, stderr, raw JSON
26+
6. **Regression check**: If test fails, re-run with `--branch master` to compare
27+
28+
## Output Structure
29+
30+
The runner returns a **concise summary** to stdout (saves context when all passes):
31+
32+
```json
33+
{
34+
"results_file": "/tmp/bat_results_abc123.json",
35+
"agents": {
36+
"gemini": {
37+
"all_passed": true,
38+
"test": {
39+
"completed": true,
40+
"duration_ms": 8100,
41+
"exit_code": 0,
42+
"num_turns": 5,
43+
"tool_stats": { "totalCalls": 4, "totalSuccess": 4, "totalFail": 0 }
44+
},
45+
"aggregate": {
46+
"total_duration_ms": 15300,
47+
"total_turns": 12,
48+
"total_tool_calls": 9,
49+
"total_tool_success": 9,
50+
"total_tool_fail": 0
51+
}
52+
}
53+
}
54+
}
55+
```
56+
57+
- **Phase stats**: `num_turns`, `tool_stats` (per phase) for fine-grained comparison
58+
- **Aggregate stats**: Total counts across all phases for overall efficiency comparison
59+
- **On failure**: also includes `output` and `stderr` for diagnosis
60+
- **Full results**: raw JSON, complete output always available at `results_file`
61+
62+
## Scenario Design Guidelines
63+
64+
- **setup_prompt**: Create any entities/state the test needs
65+
- **test_prompt**: Exercise the tools being tested, ask the agent to report results clearly
66+
- **teardown_prompt**: Clean up created entities
67+
- Keep prompts focused - each scenario tests ONE behavior
68+
- Ask the agent to report: what succeeded, what failed, any unexpected behavior
69+
70+
## Example: Testing Error Signaling
71+
72+
```bash
73+
cat <<'EOF' | python tests/uat/run_uat.py --agents gemini
74+
{
75+
"setup_prompt": "Create a test automation called 'bat_error_test' with a time trigger at 23:59 and action to turn on light.bed_light.",
76+
"test_prompt": "Try to get automation 'automation.nonexistent_xyz'. Report if the tool signaled an error or returned a normal response. Then get automation 'automation.bat_error_test' and report its structure.",
77+
"teardown_prompt": "Delete automation 'bat_error_test' if it exists."
78+
}
79+
EOF
80+
```
81+
82+
## Regression Comparison Workflow
83+
84+
**Full BAT comparison** (recommended):
85+
86+
1. **Pull latest master**: `git fetch origin master && git checkout master && git pull`
87+
2. **Run on master**: Save scenario to file, run and save results
88+
3. **Switch to branch**: `git checkout feat/my-branch`
89+
4. **Run on branch**: Run same scenario, compare stats
90+
91+
**Compare these metrics:**
92+
- **Task completion**: Did both pass? Any new failures?
93+
- **Accuracy**: Check agent output quality - did it understand the task correctly?
94+
- **Efficiency**: Compare `aggregate.total_tool_calls`, `aggregate.total_turns`, `aggregate.total_duration_ms`
95+
- **Variation testing**: Ask the same task in different ways to test robustness
96+
97+
**Quick comparison** (single command):
98+
99+
```bash
100+
# Test the PR branch
101+
echo '{"test_prompt":"..."}' | python tests/uat/run_uat.py --branch feat/tool-errors --agents gemini
102+
103+
# Compare against master
104+
echo '{"test_prompt":"..."}' | python tests/uat/run_uat.py --branch master --agents gemini
105+
```
106+
107+
## Cost Awareness
108+
109+
Each scenario invocation costs API credits (one per agent per phase). Design scenarios efficiently:
110+
111+
- Combine related checks in a single test_prompt when possible
112+
- Only use setup/teardown when the test needs specific state
113+
- Start with one agent, expand to both only when cross-agent comparison matters
114+
115+
## Handling Arguments
116+
117+
When `/bat` is invoked with arguments:
118+
119+
**If arguments contain a scenario description**, generate the JSON scenario and run it:
120+
```
121+
/bat test automation create with sunrise trigger then modify to sunset
122+
```
123+
→ Generate appropriate scenario JSON and execute
124+
125+
**If `--help` or no arguments**, show this help text.
126+
127+
**Otherwise**, treat `$ARGUMENTS` as instructions for what to test and design+run the scenario accordingly.
128+
129+
## Full Documentation
130+
131+
For complete CLI reference and output format, see `tests/uat/README.md`.

0 commit comments

Comments
 (0)