Absolutely!
What you need is a clean application environment in which you can run your tests - a blank slate.
All applications have an application delegate which sets up the initial state of the application and provides a root view controller on launch. For the purposes of testing you don't want that to happen - you need to be able to test in isolation, without all of those things happening. Ideally you want to be able to have the screen undertest and only that screen loaded, and no other state changes happen.
To do so you can create an object just for testing that implements UIApplicationDelegate
. You can tell the application to run in "testing mode" and use the testing-specific application delegate using a launch argument.
Objective-C:
main.m:
int main(int argc, char * argv[]) {
NSString * const kUITestingLaunchArgument = @"org.quellish.UITestingEnabled";
@autoreleasepool {
if ([[NSUserDefaults standardUserDefaults] valueForKey:kUITestingLaunchArgument] != nil){
return UIApplicationMain(argc, argv, nil, NSStringFromClass([TestingApplicationDelegate class]));
} else {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([ProductionApplicationDelegate class]));
}
}
}
Swift:
main.swift:
let kUITestingLaunchArgument = "org.quellish.UITestingEnabled"
if (NSUserDefaults.standardUserDefaults().valueForKey(kUITestingLaunchArgument) != nil){
UIApplicationMain(Process.argc, Process.unsafeArgv, NSStringFromClass(UIApplication), NSStringFromClass(TestingApplicationDelegate))
} else {
UIApplicationMain(Process.argc, Process.unsafeArgv, NSStringFromClass(UIApplication), NSStringFromClass(AppDelegate))
}
You will have to remove any @UIApplicationMain
annotation from your Swift classes.
For "application tests" be sure to set the "Test" action of the scheme in Xcode to provide the launch argument:
For UI tests you can set the launch arguments as part of the test:
Objective-C:
XCUIApplication *app = [[XCUIApplication alloc] init];
[app setLaunchArguments:@[@"org.quellish.UITestingEnabled"] ];
[app launch];
Swift:
let app = XCUIApplication()
app.launchArguments = [ "org.quellish.UITestingEnabled" ]
app.launch()
This allows the tests to use an application delegate specificly for testing. This empowers you with a lot of control - you now have a blank slate to work with for testing. The testing application delegate can load a specific storyboard or put in place an empty UIViewController
. As part of your UI tests you might instantiate the view controller under test and set it as the keyWindow
's root view controller or present it modally. Once it has been added or presented your tests can execute, and when complete remove or dismiss it.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…