Test Skills
Overview
Kick off Unity tests and read their XML reports. Recipes are stateless
fire-and-forget + read pairs — there is no job ID, no polling loop inside a
single Unity_RunCommand. Trigger a run in one call, read TestResults/*.xml
in a later call.
Mental model
- Install
tooling/test/test_runner_toolfirst, once per project, and start every run through it. Do not register a result callback from aUnity_RunCommandbody: such a callback can never be cleaned up, and each one rewrites its own old report with every later run's results, so a report captured as "red" becomes a copy of a later green one. It cannot be repaired in place — the failed approaches are listed under Why not inline; do not re-attempt them. - Trigger:
test_runortest_run_by_namecallsProjectTestRunner.Run(...), which returns the report path immediately.TestRunnerApi.Executewrites no file on its own; the tool's single permanent callback writes it when the run finishes. - Use a fresh report filename per run, and pass fully-qualified test names. A bare class
name matches zero tests, and a run of zero tests reports as a pass — always assert
totalis non-zero before believing a green. - Read: parse the report yourself once it has settled.
test_get_result,test_get_last_resultandtest_get_summarybelow are recipe templates underrecipes/test/, not callable MCP tools — adapt one into aUnity_RunCommandbody, or just parse the XML from the shell, which is usually less work:python3 -c "import xml.etree.ElementTree as ET;print(ET.parse('TestResults/<name>.xml').getroot().attrib)".
Polling across calls is the caller's job, not a recipe's. Only one Test
Runner run should be active at a time — the tool returns an ERROR: string if a run it started is
still pending. Wait for the report to be whole and fresh — the poll loop in
test_run — before starting the next.
Precondition: the Editor must be open and responsive on the intended project before triggering.
PlayMode caveat: a PlayMode run may trigger a domain reload that discards the in-memory callback before it fires, so no XML is written. For reliable PlayMode reports, disable domain reload for the run or use a persistent (compiled) editor runner. EditMode runs do not reload the domain.
Common Mistakes
DO NOT (common hallucinations):
test_run_alldoes not exist → usetest_runortest_run_by_name.test_create_templatedoes not exist → usetest_create_editmodeortest_create_playmode.test_get_statusdoes not exist → usetest_get_result(reads the XML, stateless).- There is no
jobIdanywhere. If older docs mention one, ignore them. - There is no
test_cancel— UnityTestRunnerApihas no public hard-cancel surface. - There is no
test_smoke_skills— it depended on an upstream REST skill registry that isn't in this pack.
Routing:
- For compile error checking →
editor_get_state(isCompilingfield). - For test script creation →
test_create_editmode/test_create_playmode, then edit via thescriptmodule.
Skills
test_run
Kick off tests. Returns { success, started, mode, filter, resultsPath }
immediately; the callback writes TestResults/<mode>-mcp.xml when the run ends.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| testMode | string | No | EditMode | EditMode or PlayMode. |
| filter | string | No | null | Test-name substring forwarded as Filter.testNames[0]. |
test_run_by_name
Kick off a single class or fully-qualified method. Returns
{ success, started, testName, mode, resultsPath }; the callback writes
TestResults/<mode>-mcp.xml when the run ends.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| testName | string | Yes | - | Exact class name or Ns.Class.Method. |
| testMode | string | No | EditMode | EditMode or PlayMode. |
test_get_result
Read the newest TestResults/<mode>-*.xml and return parsed counts.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| testMode | string | No | EditMode | Which XML family to filter on. |
Returns: { success, file, total, passed, failed, skipped, inconclusive, failedNames, startTime, endTime, durationSeconds }
test_get_last_result
Newest XML across all modes. No parameters.
Returns: { success, file, mode, total, passed, failed, skipped, inconclusive, failedNames, startTime, endTime, durationSeconds }
test_get_summary
Aggregate every XML report under TestResults/. No parameters.
Returns: { success, totalRuns, totalPassed, totalFailed, totalSkipped, totalInconclusive, allFailedTests, files }
test_list
List available tests.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| testMode | string | No | EditMode | EditMode or PlayMode. |
| limit | int | No | 100 | Max tests to list. |
test_list_categories
List test categories.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| testMode | string | No | EditMode | EditMode or PlayMode. |
test_create_editmode
Write an EditMode test template synchronously.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| testName | string | Yes | - | Class name. No /, \, ... |
| folder | string | No | Assets/Tests/Editor | Must start with Assets/ or Packages/. |
Returns: { success, path, testName }
test_create_playmode
Write a PlayMode test template synchronously.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| testName | string | Yes | - | Class name. No /, \, ... |
| folder | string | No | Assets/Tests/Runtime | Must start with Assets/ or Packages/. |
Returns: { success, path, testName }
RunCommand Examples
Recipe path rule: ../../recipes/test/<command>.md
See ../../recipes/test/<command>.md for C# templates.