Resetting iOS Simulator for UI tests
One of the major issues we encounter with UI tests in iOS is the simulator’s inability to completely clear its slate between runs. Here is an example.
The problem we’re trying to solve
Say, you’re implementing a login functionality and, like a good citizen, you’re storing the credentials in the keychain. Now, for unit and integration tests this won’t pose a problem as it can be easily mocked. But for UI tests, the app is tested as an entity, from outside, without access to internals. And the simulator doesn’t clear the keychain between tests.
Almost as bad as Xcode running tests in alphabetical order! :scream:
The Solution — app launch arguments
When starting an app as part of the UI tests, one can pass in launch arguments:
But for that to work we’re going to have a look at UIApplicationMain first.
If you came to iOS Swift development from other languages, or even if you did iOS development with Obj-C before, you might have noticed that there is no main.x file that can be used as the entry point — e.g. main.m in Obj-C. There is a @UIApplicationMain marker in AppDelegate.swift that serves the same purpose and it’s actually possible to also use a “main” file.
To be able to observe the new launch parameter “ — Reset” we’ll need to change things a bit so we can react to it.
Let’s delete @UIApplicationMain and create a main.swift file:
This simply calls UIApplicationMain which is the entry point to create the application object and the application delegate and set up the event cycle.
This now gives us the opportunity to perform tasks before launching the app.
To reset the keychain I’ve created as simple resetKeychain() method that I’ve enclosed into an enum simply to namespace:
All together now
The code is also available as a gist:
One more thing
When using the reset in UI tests I tend to create helper methods to launch the app with different arguments:
Happy UI Testing!
If you found this tutorial useful, make sure you check out my upcoming LeanPub book: