Skip to content

Instantly share code, notes, and snippets.

@joemasilotti
Last active September 13, 2022 14:20
Show Gist options
  • Star 21 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joemasilotti/74df5e13adede2e132461dfea32b441c to your computer and use it in GitHub Desktop.
Save joemasilotti/74df5e13adede2e132461dfea32b441c to your computer and use it in GitHub Desktop.
Resetting NSUserDefaults in UI Testing

Resetting NSUserDefaults in UI Testing

  1. Add "UI-Testing" to launchArguments before launching the app under test
  2. On launch, check for the argument in AppDelegate.swift
  3. If it exists remove everything for the app's domain from NSUserDefaults
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
resetStateIfUITesting()
window = UIWindow(frame: UIScreen.mainScreen().bounds)
window?.rootViewController = RootViewController()
window?.makeKeyAndVisible()
return true
}
private func resetStateIfUITesting() {
if NSProcessInfo.processInfo().arguments.contains("UI-Testing") {
NSUserDefaults.standardUserDefaults().removePersistentDomainForName(NSBundle.mainBundle().bundleIdentifier!)
}
}
}
import XCTest
class UITests: XCTestCase {
private let app = XCUIApplication()
override func setUp() {
super.setUp()
app.launchArguments += ["UI-Testing"]
app.launch()
}
}
@fishercraigj
Copy link

fishercraigj commented Jun 29, 2017

Genius. I actually took it one step further. I had a scenario for a first time user experience (which was tolled into the UserDefaults) and a whole test class with multiple test cases dedicated to it. The problem was, if you ran a test case you were no longer a new user.

I do have one "Tester" base type of class with a global setup and tear down which 99% of my tests will consume. But in this instance, I didn't want all my other tests to be treated as first time users. I wanted to delete the UserDefaults only for FTU. So in my FTU class, I simply did the same thing you did in your setup. To avoid having the launchArguments stored during my test run, I also overrode the tear down in my FTU class so that ever time that FTU test case was done, it removed the launch arguments. Hope this helps some poor schlub like me trying to figure out how to do this.

`class FTUTests: Tester {

override func setUp() {
    app.launchArguments += ["UI-Testing"]
    super.setUp()
}

override func tearDown() {
    app.launchArguments.removeAll()
    super.tearDown()
}

}`

@m-kulesza
Copy link

For swift 4 resetStateIfUITesting will looks like:

private func resetStateIfUITesting() { if ProcessInfo.processInfo.arguments.contains("UI-Testing") { UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!) } }

@Bersaelor
Copy link

This doesn't work for me anymore (Xcode 9.3.1 atm).

If I print ProcessInfo.processInfo.arguments at application start, any arguments set like app.launchArguments += ["UI-Testing"] aren't set in there.

@mikeandike
Copy link

Works great in Xcode 10!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment