XCTestDevices: the simulator clones parallel testing leaves behind
Parallel UI tests clone simulators into a folder most developers have never opened. How to measure it, and remove the clones without touching your own simulators.
Turn on parallel testing in an Xcode scheme and every test run clones your chosen simulator several times, one per test runner. The clones live in their own simulator set, separate from the simulators you see in Xcode, at ~/Library/Developer/XCTestDevices. They are meant to be temporary. They are not always cleaned up.
Measure it
du -sh ~/Library/Developer/XCTestDevices
xcrun simctl --set ~/Library/Developer/XCTestDevices list devicesEach clone carries the data of the simulator it was cloned from, including installed apps. A team that runs UI tests locally can find this folder larger than DerivedData.
Removing them
Quit Xcode and the Simulator app, and make sure no tests are running. Then delete every device in that set, and only that set:
xcrun simctl --set ~/Library/Developer/XCTestDevices delete allXcode creates fresh clones the next time parallel tests run, so this costs a slower first run and nothing else.
Why the clones stay
- Tests stopped partway, or Xcode quit during a run.
- Several Xcode versions in use, each with its own idea of which clones it owns.
- CI scripts that interrupt
xcodebuildon timeout.
On a build machine, add the delete command to the job's cleanup step. Our guides to the iOS Simulator and DerivedData cover the other large folders in ~/Library/Developer.
Common questions
What is the XCTestDevices folder?
It holds simulator clones that Xcode creates for parallel testing, in a simulator set separate from your normal simulators, at ~/Library/Developer/XCTestDevices.
Is it safe to delete XCTestDevices?
Yes, with Xcode and tests stopped. Use xcrun simctl --set ~/Library/Developer/XCTestDevices delete all, and keep the --set part so your own simulators are untouched.
Why does XCTestDevices keep growing?
Clones are meant to be removed after testing, but interrupted runs, several Xcode versions and CI timeouts leave them behind.