CI runners need a repeatable way to launch iOS UI tests without opening Xcode. xcodebuild drives the same XCTest runner from Terminal, so a macOS job can build the app, start an iOS Simulator destination, run the UI test bundle, and return a normal process exit code for the pipeline.
A CI command should name the workspace or project, scheme, simulator destination, derived data directory, and result bundle path explicitly. Those values keep the job independent of a developer's local Xcode state and leave the .xcresult bundle in a path the CI system can upload as an artifact.
A workspace named MyApp.xcworkspace, a scheme named MyApp, and an iOS Simulator destination named iPhone 16 keep the placeholders concrete without exposing a real app. Use a macOS runner with full Xcode and a matching simulator runtime; the Command Line Tools package alone does not include the Simulator utilities needed for XCUITest.
Related: How to run XCUITest tests in GitHub Actions
Related: How to run XCUITest tests locally
Related: How to save XCUITest result bundles
$ xcodebuild -version Xcode 16.4 Build version 16F6
If this command reports that the active developer directory is /Library/Developer/CommandLineTools, the runner has only the Command Line Tools package selected and cannot run iOS Simulator UI tests.
$ xcodebuild -workspace MyApp.xcworkspace -scheme MyApp -showdestinations
Available destinations for the "MyApp" scheme:
{ platform:iOS Simulator, id:<SIMULATOR-UDID>, OS:18.5, name:iPhone 16 }
Use -project MyApp.xcodeproj instead of -workspace MyApp.xcworkspace when the scheme belongs to a standalone project.
$ rm -rf TestResults/MyAppUITests.xcresult
Remove only a result bundle path inside the CI workspace. Do not point this cleanup command at shared derived data, source files, or a developer home directory.
$ xcodebuild test \ -workspace MyApp.xcworkspace \ -scheme MyApp \ -destination 'platform=iOS Simulator,name=iPhone 16,OS=latest' \ -derivedDataPath DerivedData \ -resultBundlePath TestResults/MyAppUITests.xcresult Testing started Test Suite 'MyAppUITests.xctest' passed ** TEST SUCCEEDED **
Use build-for-testing in a separate build stage and test-without-building in the test stage only when the CI job preserves the compiled test products, the same DerivedData path, or the generated .xctestrun file.
$ ls -ld TestResults/MyAppUITests.xcresult drwxr-xr-x 6 ci staff 192 Jun 26 09:15 TestResults/MyAppUITests.xcresult
Upload TestResults/MyAppUITests.xcresult as a CI artifact even when the test job fails, so failures still have logs, screenshots, and attachments available for review.