Waiting for things to happen is one of the main challenges in UI testing; I can’t click something if it’s still animating onto the screen or we’re waiting for data to load. While test frameworks do have some built-in intelligence to wait for the application to idle, they’re rarely enough to provide a reliable experience, and are very limited. Note: These patterns work equally well for unit testing, but waiting in unit tests is not really a thing, and if you’re in need of a timer you’re probably doing something wrong, but I digress.
In XCUITest, the most common way of providing a better wait is waitForExistence. I’d wager this is used 90% of the time, but what if you want to wait for something to not exist? Or to be hittable? Or contain a certain value? Functions aren’t provided for those so you’ll need to build your own. I’m not going to give away all the secret sauce here (nobody learns when you can copy + paste!), but you’re going to need a timer pattern to build these functions, of which there are two I use with regularity:
Expectations
This is the most standard method. It uses predicates, which I find somewhat difficult to work with, but the useful ones to UI testing are relatively straightforward so I’ve created helper enums to store them. Again, not giving away the secret sauce, but may in a future post about particular waits.
You create an expectation with a predicate, pass it to an XCWaiter, and it’ll give you a result.
The problem with this timer is you have no control over the polling frequency. I’ve seen this wait take one second and I’ve seen it take ten seconds regardless of what is on screen or in debug; it’s relatively inefficient.
Scheduled Timer
The other method, which I’ve baked myself, but is just about as vanilla a timer pattern comes. I typically use this when I’m looking at values of things as opposed to states as that is a much more difficult predicate to write. Unlike the Expectation method above, the granularity on the timer can also be adjusted so you can get a much faster result at the likely cost of processing power (I’ve not measured this, but since we’re not sending our UI tests to space I generally ignore things such as that). There was recently a StackOverflow question regarding this and the person went with my solution, but I’m having trouble digging that up.
The code above has been altered heavily to make it generic, and is untested, but gives the gist of the pattern.
XCToolbox Cocoapod
I know I said I wouldn’t give away the secret sauce, but I more or less already have; the timer patterns above are featured in implementations in my XCToolbox Cocoapod along with a handful of other goodies. Implement the pod into your project or simply copy + paste the bits relevant to your work.
Leave a Reply