Xcode MCP: RunAllTests runs the previously active test plan's target selection after XcodeSwitchTestPlan
Summary
mcp__xcode__RunAllTests can execute the previously active test plan's target selection instead of the currently active one, even though mcp__xcode__XcodeListTestPlans correctly reports the new plan as active. mcp__xcode__RunSomeTests (explicit {targetName, testIdentifier} list) does not have this problem and reliably runs against the active plan/destination.
Setup
- An Xcode project/scheme with two
.xctestplanfiles, each enabling a different unit-test target and disabling the other, e.g.: PlanA.xctestplan: targetUnitTestsAenabled, targetUnitTestsBdisabledPlanB.xctestplan: targetUnitTestsBenabled, targetUnitTestsAdisabled- Both plans registered on the scheme's
TestPlanslist (.xcscheme).
Repro steps
XcodeSwitchTestPlan(testPlanName: "PlanA")— active plan isPlanA.RunAllTests— runsUnitTestsAonly, as expected.XcodeSwitchTestPlan(testPlanName: "PlanB")— tool reportsactiveTestPlanName: "PlanB".XcodeListTestPlans— confirmsPlanBis active (isActive: true),PlanAis not.RunAllTests— top-level result still saysactiveTestPlanName: "PlanB", but the actual test run executesUnitTestsA's tests (all "Passed") and reports everyUnitTestsBtest as"No result"— the inverse of what the active plan specifies.- The console log for that run (
fullConsoleLogsPath) shows only one app install/launch, for the host app runningUnitTestsA's bundle —UnitTestsB's bundle is never launched, only mentioned in the trailing code-coverage summary ("Generating entry for target UnitTestsB.xctest" with "Skipped N file(s) with no executable lines").
Expected
RunAllTests should run whatever GetTestList/XcodeListTestPlans reports as the active plan's enabled tests — i.e. UnitTestsB in step 5.
Actual
RunAllTests silently ran the stale, previously-active plan's target selection. No error was surfaced; the result shape looks identical to a normal successful run (real Pass/Fail states for the tests that did run), so this is easy to miss — the only tell is that the "wrong" target's tests passed and the "right" target's tests all show "No result".
Workaround found
Calling RunSomeTests with an explicit list of {targetName: "UnitTestsB", testIdentifier: "..."} pairs (enumerated from GetTestList while PlanB is active) runs the correct tests every time, with real results — this suggests the destination/build-for-testing itself is fine and the bug is specifically in how RunAllTests resolves "the active plan's selection" right after a plan switch (looks like a stale cache of the previous plan's derived -only-testing/-skip-testing argument list).
Impact
Anyone scripting "switch plan → run all tests" (e.g. to separate simulator-safe tests from device-only tests across two plans on the same scheme) gets silently wrong results — tests that should be skipped report as passed (from the old plan), and tests that should run report as not run, with no indication anything went wrong. Re-running RunAllTests a second time after the switch, or using RunSomeTests with explicit identifiers, both work around it.
Environment
- Claude Code desktop app, built-in Xcode MCP tools (
mcp__xcode__*) - Xcode with a multi-test-plan scheme (this repro used 3 plans total, only 2 involved in the switch)
- Reproduced against both a Simulator destination and a physical device destination
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗