by
When you are writing UI tests for an iOS it is likely that you will encounter cases where your test needs to interact with an alert presented by the system.
XCTest provides API to handle these cases with addUIInterruptionMonitor(withDescription:handler:)
and the corresponding method to remove this monitor on XCTestCase
.
If your app does some setup to explain why a permission is required your UI flow may be as follows:
To test this with a UI test you might do the following:
You will likely not reach step 4 with your test initially.
To illustrate why this happens it may be helpful to study the transcript of a passing test case test case:
Test Case '-[SimpleUITestUITests.SimpleUITestUITests testGrantingPermissions]' started.
t = 0.00s Start Test at 2019-04-25 07:33:34.747
t = 0.06s Set Up
t = 0.07s Open sean.systems.SimpleUITest
t = 0.10s Launch sean.systems.SimpleUITest
t = 1.53s Wait for accessibility to load
t = 2.65s Wait for sean.systems.SimpleUITest to idle
t = 3.98s Tap "Grant Permission" Button
t = 3.98s Wait for sean.systems.SimpleUITest to idle
t = 4.01s Find the "Grant Permission" Button
t = 4.05s Check for interrupting elements affecting "Grant Permission" Button
t = 4.05s Synthesize event
t = 4.15s Wait for sean.systems.SimpleUITest to idle
t = 4.62s Tap Target Application 'sean.systems.SimpleUITest'
t = 4.62s Wait for sean.systems.SimpleUITest to idle
t = 4.65s Find the Target Application 'sean.systems.SimpleUITest'
t = 4.67s Check for interrupting elements affecting "SimpleUITest" Application
t = 4.67s Wait for com.apple.springboard to idle
t = 4.70s Snapshot accessibility hierarchy for app with pid 3409
t = 4.75s Find: Descendants matching type Alert
t = 4.77s Handle interrupting element
t = 4.77s Find the "Always Allow" Button
t = 4.77s Snapshot accessibility hierarchy for app with pid 3409
t = 4.82s Find: Descendants matching type Alert
t = 4.82s Find: Identity Binding
t = 4.82s Find: Descendants matching type Button
t = 4.83s Find: Elements matching predicate '"Always Allow" IN identifiers'
t = 4.84s Tap "Always Allow" Button
t = 4.84s Wait for com.apple.springboard to idle
t = 4.87s Find the "Always Allow" Button
t = 4.87s Snapshot accessibility hierarchy for app with pid 3409
t = 4.91s Find: Descendants matching type Alert
t = 4.91s Find: Identity Binding
t = 4.91s Find: Descendants matching type Button
t = 4.91s Find: Elements matching predicate '"Always Allow" IN identifiers'
t = 4.91s Check for interrupting elements affecting "Always Allow" Button
t = 4.91s Snapshot accessibility hierarchy for app with pid 3409
t = 4.94s Find: Descendants matching type Alert
t = 4.95s Synthesize event
t = 5.04s Wait for com.apple.springboard to idle
t = 5.10s Waiting 10.0s for "Allow “SimpleUITest” to access your location?" Alert to not exist
t = 6.11s Checking `Expect predicate `exists == 0` for object "Allow “SimpleUITest” to access your location?" Alert`
t = 6.11s Checking existence of `"Allow “SimpleUITest” to access your location?" Alert`
t = 6.11s Snapshot accessibility hierarchy for app with pid 3409
t = 6.14s Find: Descendants matching type Alert
t = 6.66s Check for interrupting elements affecting "SimpleUITest" Application
t = 6.67s Synthesize event
t = 6.75s Wait for sean.systems.SimpleUITest to idle
t = 6.78s Waiting 10.0s for "Permission Granted" StaticText to exist
t = 7.79s Checking `Expect predicate `exists == 1` for object "Permission Granted" StaticText`
t = 7.79s Checking existence of `"Permission Granted" StaticText`
t = 7.81s Tap "Permission Granted" StaticText
t = 7.81s Wait for sean.systems.SimpleUITest to idle
t = 7.84s Find the "Permission Granted" StaticText
t = 7.85s Check for interrupting elements affecting "Permission Granted" StaticText
t = 7.86s Synthesize event
t = 7.94s Wait for sean.systems.SimpleUITest to idle
t = 7.96s Tear Down
Test Case '-[SimpleUITestUITests.SimpleUITestUITests testGrantingPermissions]' passed (8.166 seconds).
First the Grant Permission button is tapped, causing the iOS permission request alert to be presented.
Next, the app is tapped. This causes the interruption monitor to inspect the alert and perform the actions defined in the handler — because the alert is blocking interaction with the app.
Notice also that the interruption monitor is only consulted after the UI test runner matches an element to interact with. If you attempt to match an element which is only expected to be present after the permission is granted or denied your test will not succeed.
Thus this presents two options for ensuring the interruption handler is executed during a UI test case:
Configuration: Xcode 10.2 (10E125)
tags: