问题
Apple introduced in Xcode 7 new UI Testing but I have a struggle whenever the tests launches the app, it starts with data that the application had before. It means tests cannot be independent and can be influenced by other tests.
It is not possible to access user defaults and other data because the application that is running tests has no access to the bundle of the tested application. Scripts are also out of question because they can be run before or after testing. And there is no way how to execute NSTask on iOS to run a script before each test suite.
Is there a way how do reset the application data before each test suite?
回答1:
Not in a straight forward manner. But there are some workarounds.
The XCUIApplication
can set command line arguments and environment variables that can alter your application’s behavior.
A simple example of your main.m
file:
int main(int argc, char * argv[]) {
#if DEBUG
// Reset all data for UI Testing
@autoreleasepool {
for (int i = 1; i < argc; ++i) {
if (0 == strcmp("--reset-container", argv[i])) {
NSArray *folders = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSFileManager *fm = [[NSFileManager alloc] init];
for (NSString *path in folders) {
[fm removeItemAtPath:path error:nil];
}
// Also remove documents folder if necessary...
}
}
}
#endif
@autoreleasepool {
return UIApplicationMain(argc, argv, nil,
NSStringFromClass([AppDelegate class]));
}
}
And in -[XCTestCase setUp]
add:
XCUIApplication *app = [[XCUIApplication alloc] init];
app.launchArguments = @[@"--reset-container"];
[app launch];
回答2:
If preparing the app for UITests inside application:didFinishLaunchingWithOptions:
is ok in your case, then you can do the following:
In setUp()
method of your test class extending XCTestCase
add following code:
let application = XCUIApplication()
application.launchEnvironment = ["UITESTS":"1"]
application.launch()
Then, in application:didFinishLaunchingWithOptions:
you can check for the flag using following code:
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
let env = ProcessInfo.processInfo.environment
if let uiTests = env["UITESTS"], uiTests == "1" {
// do anything you want
}
// further set up code
}
Of course if that is an option for you.
NOTE: Instead of setting "1"
as argument for "UITESTS"
flag, you can specify different values for different test cases - or even test methods (but in such case, you should launch the application from test method, not setUp()
)
NOTE 2: I suggest wrapping the code dealing with the flag into #if DEBUG
block.
回答3:
I got to reset the application data using some private headers to access to the springboard and the settings app.
First I added a Run script phase to remove it when the tests starts:
/usr/bin/xcrun simctl uninstall booted com.mycompany.bundleId
And after that I use the solution I wrote here to remove it using a test script that runs on the tearDown
calls to reset it after every test.
回答4:
In my case I required to also reset permissions. And there's an option to delete your app and reset system permissions just making the test delete the app and navigate to settings.
Already answered in this S.O. thread: Is there a way to reset the app between tests in Swift XCTest UI in Xcode 7?
来源:https://stackoverflow.com/questions/32351149/how-do-i-reset-the-application-data-after-each-test-with-xcode-7-ui-testing