如何检测iOS应用程序是否在UItesting模式下运行

我希望我的应用程序在UItesting模式下运行时运行特殊代码(例如重置其状态)。 我查看了应用程序从UItesting运行时设置的环境variables,并且没有任何明显的参数来区分应用程序正常运行与UItesting。 有没有办法找出答案?

我不满意的两个解决方法是:

  1. 设置XCUIApplication.launchEnvironment与我稍后在应用程序中检查的一些variables。 这不好,因为你必须在每个testing文件的setUp方法中设置它。 我试图从scheme设置中设置环境variables,但是在运行UItestingtesting时不会传播到应用程序本身。
  2. 检查是否存在环境variables__XPC_DYLD_LIBRARY_PATH 。 这看起来很不好,现在可能只能工作了,因为我们有如何设置目标构build设置的巧合。

我一直在研究这个问题,并且遇到了这个问题。 我结束了@ LironYahdav的第一个解决方法:

在你的UItesting中:

 - (void)setUp { [super setUp]; XCUIApplication *app = [[XCUIApplication alloc] init]; app.launchEnvironment = @{@"isUITest": @YES}; [app launch]; } 

在你的应用程序:

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

@ JoeMasilotti的解决scheme对单元testing非常有用,因为它们与正在testing的应用程序共享相同的运行时间,但与UItesting无关。

我没有设置启动环境的成功,但得到启动参数的工作。

在你的testingsetUp()函数中添加:

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

在您的生产代码中添加一个如下的检查:

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

使用XCode 7.1.1进行validation。

您可以使用预处理器macros 。 我发现你有几个select:

新目标

制作应用程序目标的副本,并将其用作要testing目标 。 此目标副本中的任何预处理器macros都可以在代码中访问。

一个缺点是你将不得不添加新的类/资源到复制目标,有时很容易忘记。

新的生成configuration

复制Debug构buildconfiguration,将任何预处理器macros设置为此configuration并将其用于您的testing(请参见下面的屏幕截图)。

小问题:每当你想logging一个UItesting会话,你需要改变运行使用新的testingconfiguration。

添加一个重复的configuration:

添加一个重复的conf

使用它为您的testing

用它来测试*

我刚刚添加了这个扩展

  @available(iOS 9, *) extension XCUIApplication { func test(){ launchEnvironment = ["TEST":"true"] launch() } } 

所以我可以用test()代替launch()

在Swift 3中,你可以检查XCInjectBundleInto键,或者以XC开头的东西。

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

这也适用于OS X。

Swift 3根据以前的答案。

 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") } } 

然后在代码中调用UIApplication.isRunningTest。

我认为最简单的做法是在应用程序启动后在用户界面中放置一些复活节彩蛋,然后在应用程序中检查复活节彩蛋。 因此,如果先点击某个button10X,那么会设置一个用户设置或环境variables,或者随后在应用程序中检查的任何内容。 这似乎有点不好意思,但我无法想出任何其他方式来做到这一点。

这两个进程有自己的一组环境variables,用户缺省值和启动选项。