How to detect if iOS app is running in UI Testing mode

微笑、不失礼 提交于 2019-11-28 19:08:06

I've been researching this myself and came across this question. I ended up going with @LironYahdav's first workaround:

In your UI test:

- (void)setUp
{
    [super setUp];

    XCUIApplication *app = [[XCUIApplication alloc] init];
    app.launchEnvironment = @{@"isUITest": @YES};
    [app launch];
}

In your app:

NSDictionary *environment = [[NSProcessInfo processInfo] environment];
if (environment[@"isUITest"]) {
    // Running in a UI test
}

@JoeMasilotti's solutions are useful for unit tests, because they share the same runtime as the app being tested, but are not relevant for UI tests.

I didn't succeed with setting a launch environment, but got it to work with launch arguments.

In your tests setUp() function add:

  let app = XCUIApplication()
  app.launchArguments = ["testMode"]
  app.launch()

In your production code add a check like:

let testMode =  NSProcessInfo.processInfo().arguments.contains("testMode")
if testMode {
  // Do stuff
}

Verified using XCode 7.1.1.

Sandeep Chayapathi

You can use Preprocessor Macros for this. I found that you have couple of choices:

New Target

Make a copy of the App's target and use this as the Target to be Tested. Any preproocessor macro in this target copy is accessible in code.

One drawback is you will have to add new classes / resources to the copy target as well and sometimes it very easy to forget.

New Build Configuration

Make a duplicate of the Debug build configuration , set any preprocessor macro to this configuration and use it for your test (See screenshots below).

A minor gotcha: whenever you want to record a UI Testing session you need to change the Run to use the new testing configuration.

Add a duplicate configuration:

Use it for your Test:

I've just added this extension

 @available(iOS 9, *)
 extension XCUIApplication {

 func test(){
   launchEnvironment = ["TEST":"true"]
   launch()
  }
 }

So I can just use test() instead of launch()

Swift 3 based on previous answers.

class YourApplicationUITests: XCTestCase {

    override func setUp() {
        super.setUp()

        // Put setup code here. This method is called before the invocation of each test method in the class.

        // In UI tests it is usually best to stop immediately when a failure occurs.
        continueAfterFailure = false
        // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
        let app = XCUIApplication()
        app.launchArguments = ["testMode"]
        app.launch()

        // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
    }

    override func tearDown() {
        // Put teardown code here. This method is called after the invocation of each test method in the class.
        super.tearDown()
    }

    func testExample() {
        // Use recording to get started writing UI tests.
        // Use XCTAssert and related functions to verify your tests produce the correct results.
    }

}


extension UIApplication {
    public static var isRunningTest: Bool {
        return ProcessInfo().arguments.contains("testMode")
    }
}

Then just call UIApplication.isRunningTest in your code.

In Swift 3 you can check for the XCInjectBundleInto key, or something that starts with XC.

let isInTestMode = ProcessInfo.processInfo.environment["XCInjectBundleInto"] != nil

This works in OS X as well.

My solution is almost identical to that of Ciryon above, except that for my macOS Document-based app I had to prepend a hyphen to the argument name:

let app = XCUIApplication()
app.launchArguments.append("-Testing")
app.launch() 

...otherwise, "Testing" ends up interpreted as the name of the document to open when launching the app, so I was getting an error alert:

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!