# Mode B: Testing Center Batch Testing — Full Reference
Testing Center is Salesforce's built-in test infrastructure for Agentforce agents. Tests are deployed as metadata to the org and can be run via CLI or Setup UI.
## Phase 1: Create Test Spec YAML
The Testing Center uses a specific YAML format. Create a temporary spec file:
| `testCases` | Yes | Array of test case objects |
| `testCases[].utterance` | Yes | User input message to test |
| `testCases[].expectedTopic` | No | Expected topic name |
| `testCases[].expectedActions` | No | Flat list of action name strings |
| `testCases[].expectedOutcome` | No | Natural language description (LLM-as-judge) |
| `testCases[].conversationHistory` | No | Prior conversation turns for multi-turn tests |
| `testCases[].contextVariables` | No | Session context variables |
### Key Rules
-`expectedActions` is a **flat string array**, NOT objects: `["action_a", "action_b"]`
- Action assertion uses **superset matching**: test PASSES if actual actions include all expected actions
- **Transition actions** (`go_home_search`, `go_escalation`) appear in `actionsSequence` alongside real actions. The superset matching handles this correctly -- you don't need to list transition actions.
-`expectedOutcome` uses LLM-as-judge evaluation -- describe the desired behavior in natural language
- Missing `expectedOutcome` causes a harmless ERROR in `output_validation` but topic/action assertions still pass
- **Always add `expectedOutcome`** -- it is the most reliable assertion type (LLM-as-judge scores 5/5 consistently for correct behavior) and works even when topic/action assertions can't capture nuanced behavior
### Single-Turn vs Multi-Turn Considerations
- Single-turn tests only capture the first response. If an action requires info collection first (e.g. identity verification asks for email before calling `verify_customer`), the action won't fire in one turn.
- For multi-turn workflows, either: (1) omit `expectedActions` and rely on `expectedOutcome`, or (2) use `conversationHistory` to simulate prior turns.
- For guardrail tests (off-topic), omit `expectedTopic` and use `expectedOutcome` only -- the agent correctly stays in `entry` which has no matching topic assertion. NOTE: The generated XML still includes an empty `topic_assertion` expectation, which will return `FAILURE` with score=0. This is expected and harmless -- only check the `output_validation` result for guardrail tests.
### Parsing Results for Guardrail/Safety Tests
When summarizing results, filter out `topic_assertion` FAILURE for tests that have no
`expectedTopic` set. These are false negatives caused by the empty assertion XML. Count
only `output_validation` results for these tests. Example:
```python
# When parsing results, skip topic_assertion for guardrail tests
if r['name'] == 'topic_assertion' and not has_expected_topic:
continue # Skip -- empty assertion always fails
# ... process other results
```
## Phase 2: Deploy and Run Tests
`sf agent test create` takes the YAML spec, converts it to `AiEvaluationDefinition` metadata XML, and deploys it to the org. The XML is written to `force-app/main/default/aiEvaluationDefinitions/` as part of the SFDX project.
```bash
# Step 1: Check if Testing Center is available
sf agent test list --json -o <org>
# Step 2: Deploy the test suite (writes XML to force-app/ and deploys to org)
- **Level 2** (invocation): under `topic > reasoning > actions:` — wires actions to the LLM (e.g. `check_order: @actions.get_order_status`)
Testing Center reports **Level 2 invocation names** (e.g. `check_order`), NOT Level 1 definition names (e.g. `get_order_status`). Using Level 1 names in `expectedActions` causes action assertions to FAIL even when the agent correctly invokes the action. Always use the Level 2 name from `reasoning: actions:`.