A failing UI assertion often shows what the test saw, but not what the app logged while the simulator handled the tap, request, or navigation. A scoped iOS Simulator unified-log capture gives the app messages for the same run window so a login, deep link, permission, or network failure can be matched to app-side behavior.
xcrun simctl spawn booted runs the macOS log tool inside the booted simulator. Filtering by the app's OSLog subsystem keeps the file small enough to review beside the .xcresult bundle instead of collecting every SpringBoard and system daemon message.
Start the log stream before the target UI test, let the stream stop after a fixed timeout, then compare the saved lines with the failing test in Xcode. A physical iPhone or iPad uses Xcode's device console or another device-log collector; the simulator command path is for local or CI-style simulator runs with full Xcode selected.
Related: How to run XCUITest tests locally
Related: How to run XCUITest with xcodebuild in CI
Related: How to save XCUITest result bundles
Related: How to debug a flaky XCUITest test
$ mkdir -p TestResults
$ xcrun simctl spawn booted log stream \ --style compact \ --level info \ --timeout 12m \ --predicate 'subsystem == "com.example.MyApp"' \ > TestResults/LoginUITests-device.log
Replace com.example.MyApp with the app's Logger or OSLog subsystem. For older NSLog-only apps, use --process MyApp instead of the predicate after the app has launched.
$ xcodebuild test \ -workspace MyApp.xcworkspace \ -scheme MyApp \ -destination 'platform=iOS Simulator,name=iPhone 16,OS=latest' \ -only-testing:MyAppUITests/LoginUITests/testValidLogin \ -resultBundlePath TestResults/LoginUITests.xcresult Test Suite 'Selected tests' started. Test Case '-[MyAppUITests.LoginUITests testValidLogin]' started. Test Case '-[MyAppUITests.LoginUITests testValidLogin]' failed (5.812 seconds). ** TEST FAILED **
Use -project MyApp.xcodeproj instead of -workspace MyApp.xcworkspace for a standalone project. Remove -only-testing:MyAppUITests/LoginUITests/testValidLogin when the whole UI test bundle should run.
--timeout 12m prevents a forgotten stream from running indefinitely. Increase it only when the selected test normally runs longer.
$ cat TestResults/LoginUITests-device.log Timestamp Type Process[PID] Message 2026-06-26 09:41:11.846 Info MyApp[1842] [Login] Login button tapped 2026-06-26 09:41:12.431 Error MyApp[1842] [Network] POST /session returned 401 2026-06-26 09:41:12.770 Info MyApp[1842] [Login] Showing invalid credentials message
If the file is empty, the predicate is too narrow, the simulator was not booted, or the stream started after the app exited. Re-run with the app's process name or a broader subsystem filter before collecting unrelated system logs.
$ open TestResults/LoginUITests.xcresult
In Xcode, select the failed test, inspect the failure screenshot or activity timeline, and keep TestResults/LoginUITests-device.log with the .xcresult bundle when filing a bug or CI artifact.
Related: How to save XCUITest result bundles