Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS 9 UI Testing - Test Fails Because Target Control Isn't Available (yet)

I am testing the new UI testing functionality of Xcode 7 (introduced in the WWDC 2015 video "UI Testing in Xcode").

On launch, my app animates a "login panel" into view, by updating the value of its vertical layout constraint: the panel slides up into view from beneath the main view (off screen).

The panel contains two text fields, for user name and password.

When you tap the return key on the keyboard for the user name text field (labeled "Next"), the password textfield becomes first responder. When you tap the retrun key for the password text field (labeled "Go"), the panel is "dismissed" (i.e., animated back off screen), an activity indicator starts to spin and authentication begins.

I recorded a test performing the actions described above, but when I try to "reproduce" it, it fails seemingly because the text fields are not available for input right away:

Test Suite 'Selected tests' started at 2015-08-14 13:14:19.454 Test Suite 'MyAppUITests' started at 2015-08-14 13:14:19.454 Test Case '-[MyAppUITests.MyAppUITests testExample]' started.
t = 0.00s Start Test
t = 0.00s Set Up
t = 0.00s Launch com.myCompany.MyApp 2015-08-14 13:14:19.953 XCTRunner[4667:451922] Continuing to run tests in the background with task ID 1
t = 2.64s Waiting for accessibility to load
t = 6.20s Wait for app to idle
t = 6.49s Tap "User ID" TextField
t = 6.49s Wait for app to idle
t = 6.57s Find the "User ID" TextField
t = 6.57s Snapshot accessibility hierarchy for com.myCompany.MyApp
t = 6.60s Find: Descendants matching type TextField
t = 6.60s Find: Elements matching predicate '"User ID" IN identifiers'
t = 6.60s Wait for app to idle
t = 6.67s Synthesize event
t = 6.74s Scroll element to visible
t = 6.78s Assertion Failure: UI Testing Failure - Failed to scroll to visible (by AX action) TextField 0x7fc90251a130: traits: 146029150208, {{107.0, 807.0}, {200.0, 30.0}}, placeholderValue: 'User ID', value: fffffaaaa, error: Error -25204 performing AXAction 2003 :0: error: -[MyAppUITests.MyAppUITests testExample] : UI Testing Failure - Failed to scroll to visible (by AX action) TextField 0x7fc90251a130: traits: 146029150208, {{107.0, 807.0}, {200.0, 30.0}}, placeholderValue: 'User ID', value: fffffaaaa, error: Error -25204 performing AXAction 2003
t = 6.78s Tear Down Test Case '-[MyAppUITests.MyAppUITests testExample]' failed (6.783 seconds).
Test Suite 'MyAppUITests' failed at 2015-08-14 13:14:26.238.
Executed 1 test, with 1 failure (0 unexpected) in 6.783 (6.784) seconds

(emphasis mine. Project name and bundle id changed to fake values)

How can I handle a UI like this? (i.e., test code has to wait for a certain animation to complete before the target control becomes operable)

I can't remember the video mentioning these kind of 'timing' issues.

like image 262
Nicolas Miari Avatar asked Aug 14 '15 04:08

Nicolas Miari


1 Answers

I would recommend against ticking the run loop and instead use the built in XCTest asynchronous API. For example:

let app = XCUIApplication()
app.launch()

let textField = app.textField["user name"]
let existsPredicate = NSPredicate(format: "exists == 1")

expectationForPredicate(existsPredicate, evaluatedWithObject: textField, handler: nil)
waitForExpectationsWithTimeout(5, handler: nil)

textField.tap()
textField.type("joemasilotti")

This will wait until the text field with accessibility label/identifier "username" actually exists on the screen. Then it will tap on the text field, making it active, and type my username. If five seconds pass before this becomes true the test will fail.

I have also written a post on how to use UI Testing on my blog and put together a UI Testing Cheat Sheet for scenarios like this.

like image 71
Joe Masilotti Avatar answered Oct 04 '22 16:10

Joe Masilotti