CalcSnippets
Mobile Development 2 min read

Automate iOS Simulator Smoke Tests with `simctl`

Use a small xcrun simctl script to create a clean simulator, install an app, launch it, collect a screenshot, and preserve useful logs.

A simulator script should be disposable

Manual simulator testing accumulates state. Permissions, keychains, cached data, and an old app installation can make a regression appear or disappear. For a smoke test, a disposable simulator is easier to reason about than a favorite device that has been used for weeks.

First inspect the names supported by the installed Xcode:

xcrun simctl list devicetypes
xcrun simctl list runtimes

The device type and runtime are separate identifiers. Copying a runtime name from one machine to another can fail when Xcode versions differ, so keep the discovery command close to the script.

Create, boot, install, launch

The minimal sequence is:

DEVICE_ID=$(xcrun simctl create "Smoke Test" "iPhone 16" "iOS 18.5")
trap 'xcrun simctl shutdown "$DEVICE_ID"; xcrun simctl delete "$DEVICE_ID"' EXIT
xcrun simctl boot "$DEVICE_ID"
xcrun simctl bootstatus "$DEVICE_ID" -b
xcrun simctl install "$DEVICE_ID" build/Build/Products/Debug-iphonesimulator/App.app
xcrun simctl launch "$DEVICE_ID" com.example.app

bootstatus -b gives the script a reliable wait point. Without it, an install or launch can race the simulator boot and produce an intermittent failure that looks like an application problem.

Capture evidence before cleanup

Capture a screenshot and relevant logs before the trap deletes the device:

xcrun simctl io "$DEVICE_ID" screenshot /tmp/smoke-test.png
xcrun simctl spawn "$DEVICE_ID" log show --last 2m --style compact \
  --predicate 'process == "com.example.app"'

For deterministic tests, seed only the state the scenario needs. A script that creates a clean device but then depends on a manually configured account is not reproducible. Consider adding simctl privacy, simctl status_bar, or a controlled launch argument when the test requires it.

Do not treat a successful process launch as a passing user flow. Add a UI test, a screenshot comparison, or a log assertion that represents the behavior you care about. The shell script is the environment harness; it is not the assertion.

The iOS simctl Workflow Generator creates a disposable-device starting point with cleanup, install, launch, screenshot, and log commands. Check the device and runtime names against the local Xcode installation before running it.

Keep reading

Related guides