Since Xcode 7 we have a nice API for UI testing. Mostly I\'m satisfied with it. The only concern is related to the speed.
In the beginning an ordina
Add it in didFinishLaunch
[UIApplication sharedApplication].keyWindow.layer.speed = 2;
The default value is 1, make it 2 to double its speed.
Another possibility is to disable animations at all:
[UIView setAnimationsEnabled:NO];
Swift 3:
UIView.setAnimationsEnabled(false)
Run them in parallel.
If you have only 1 build machine, you can use Bluepill: https://github.com/linkedin/bluepill
If you have multiple machines, you can use Emcee: https://github.com/avito-tech/Emcee (it also works for a single machine setup)
We have 50 hours of UI tests, and Emcee allows us to run them in 1 hour. There are several tricks to make UI tests faster, but it is pointless if you are not running them in parallel. E.g. you can't make your 25 seconds tests run in 0.5 second.
Tricks:
XCUIApplication(
privateWithPath: nil,
bundleID: "your.bundle.id"
)
Note: you should launch app with XCUIApplication().launch()
at least once per launching XCUI test runner to install the app. This requires usage of private API.
let someDataFromApi = getSomeData() // start request asynchronously and immediately return
launchApp() // this can be few seconds
useInTest(someDataFromApi) // access to data will wait request to finish
You can make the code look like there is no asynchronous things, it would be easier for QA. We want to implement this, but we didn't, so it is just an idea.
Switch to EarlGrey and make tests that lasts few seconds (but they will not be black box).
Open screens via deep links if you have deep links.
Use a lot of private API and other hacks. E.g.: instead of going via UI to Settings app and then reset privacy settings you can call some private API.
Never use long sleeps. Use polling.
Speed up animations. Do not disable them!
Pass some flags from UI tests to app to skip initial alerts/tutorials/popups. Can save a lot of time. Be sure to have at least 1 test that checks that those alerts work.
Try setting this property when your UI tests run:
UIApplication.shared.keyWindow?.layer.speed = 100
Here's how I set it:
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
if ProcessInfo.processInfo.arguments.contains("UITests") {
UIApplication.shared.keyWindow?.layer.speed = 100
}
}
And in my UI tests:
class MyAppUITests: XCTestCase {
// MARK: - SetUp / TearDown
override func setUp() {
super.setUp()
let app = XCUIApplication()
app.launchArguments = ["UITests"]
app.launch()
}
}
There's a few more handy tips in this blog post.
Following @Mark answer, the Swift 3 version:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
if ProcessInfo.processInfo.arguments.contains("UITests") {
UIApplication.shared.keyWindow?.layer.speed = 200
}
}
On you ui test file:
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
let app = XCUIApplication()
app.launchArguments = ["UITests"]
app.launch()
I wanted to disable ALL animations during Snapshot testing. I was able to able to achieve this by disabling both Core Animation and UIView animations as below.
Note because my app used storyboards UIApplication.shared.keyWindow
was nil at launch so I access the UIWindow by referring to the window
property directly.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
if ProcessInfo.processInfo.arguments.contains("SnapshotTests") {
// Disable Core Animations
window?.layer.speed = 0
// Disable UIView animations
UIView.setAnimationsEnabled(false)
}
return true
}