在Xcode中检测单元测试是否在运行时运行的正确方法是什么?

时间:2014-07-11 00:45:21

标签: objective-c ocunit xctest

当我运行单元测试时,我想跳过一些代码(例如,我不希望[[UIApplication sharedApplication] openURL:..]运行)。我正在寻找运行时检查我是否正在运行单位测试。

我知道如果单元测试正在运行但又找不到它,我已经看过检查Objective-C运行时的代码。

7 个答案:

答案 0 :(得分:17)

您可以使用this method

中的google-toolbox-for-mac
// Returns YES if we are currently being unittested.
+ (BOOL)areWeBeingUnitTested {
  BOOL answer = NO;
  Class testProbeClass;
#if GTM_USING_XCTEST // you may need to change this to reflect which framework are you using
  testProbeClass = NSClassFromString(@"XCTestProbe");
#else
  testProbeClass = NSClassFromString(@"SenTestProbe");
#endif
  if (testProbeClass != Nil) {
    // Doing this little dance so we don't actually have to link
    // SenTestingKit in
    SEL selector = NSSelectorFromString(@"isTesting");
    NSMethodSignature *sig = [testProbeClass methodSignatureForSelector:selector];
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig];
    [invocation setSelector:selector];
    [invocation invokeWithTarget:testProbeClass];
    [invocation getReturnValue:&answer];
  }
  return answer;
}

使用NSClassFromStringNSInvocation的原因是允许代码编译而不链接到xctest或ocunit

答案 1 :(得分:12)

选择项目,然后选择测试目标:

enter image description here

选择Build Settings,然后选择All and Combined。输入' preproc'在搜索框中 - 您在预处理器宏之后。

enter image description here

将一个宏添加到名为TEST的调试配置中,并将其设置为1

enter image description here

然后在您的代码中,您可以执行此操作:

#ifndef TEST
    [[UIApplication sharedApplication] doEvilThingForTesting];
#endif 

或者,如果您有在测试环境中运行的代码:

#ifdef TEST
    [[UIApplication sharedApplication] doAwesomeTestOnlyThing];
#endif 

它不完全是运行时,但是单元测试人员在运行测试IIRC之前编译代码,所以它应该是相同的效果 - 你实际上是在修改代码在运行测试之前。

答案 2 :(得分:12)

而是我正在测试?#34;在整个生产代码中的条件,我将支票隔离到一个地方:main。在那里,我检查了一个备用应用程序委托进行测试。如果它可用,我使用它而不是常规应用程序委托。这完全绕过了常规的启动顺序:

int main(int argc, char *argv[])
{
    @autoreleasepool {
        Class appDelegateClass = NSClassFromString(@"TestingAppDelegate");
        if (!appDelegateClass)
            appDelegateClass = [AppDelegate class];
        return UIApplicationMain(argc, argv, nil, NSStringFromClass(appDelegateClass));
    }
}

您可以在此处详细了解此技术:How to Easily Switch Your iOS App Delegate for Testing

答案 3 :(得分:6)

我认为您可以像Xcode 7.3一样检查

-(BOOL) isRunningUnitTests
{
    NSDictionary* environment = [ [ NSProcessInfo processInfo ] environment ];
    NSString* theTestConfigPath = environment[ @"XCTestConfigurationFilePath" ];
    return theTestConfigPath != nil;
}

答案 4 :(得分:3)

我不确定这会持续多久,但它现在适用于版本9.0 beta 6(9M214v)。

let isTesting = { () -> Bool in
    if let _ = ProcessInfo.processInfo.environment["XCTestConfigurationFilePath"] {
        return true
    } else if let testingEnv = ProcessInfo.processInfo.environment["DYLD_INSERT_LIBRARIES"] {
        return testingEnv.contains("libXCTTargetBootstrapInject.dylib")
    } else {
        return false
    }
}()

不需要更改构建环境或方案。

根据您是运行单个测试用例还是整个测试套件,似乎有两个不同的环境变量。此外,变量值也会有所不同,具体取决于您是在模拟器中还是在真实设备上运行。

答案 5 :(得分:2)

最简单的方法(并在Xcode 7中使用XCTest!)检查方法是查看匹配的O(n^2)包的进程信息:

xctest

来源:https://www.objc.io/issues/1-view-controllers/testing-view-controllers/#integration-with-xcode

答案 6 :(得分:1)

请使用:

+ (BOOL)isUnitTestRunning
{
    Class testProbeClass;
    testProbeClass = NSClassFromString(@"XCTestProbe");
    return (testProbeClass != nil);
}