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

Ron*_*nak 16 objective-c ocunit xctest

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

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

Bry*_*hen 17

您可以使用此方法谷歌工具箱换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;
}
Run Code Online (Sandbox Code Playgroud)

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


Und*_*ndo 12

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

在此输入图像描述

选择Build Settings并选择All and Combined.在搜索框中键入"preproc" - 您在预处理器宏之后.

在此输入图像描述

将一个宏添加到调用的Debug配置中TEST,并将其设置为1:

在此输入图像描述

然后在您的代码中,您可以这样做:

#ifndef TEST
    [[UIApplication sharedApplication] doEvilThingForTesting];
#endif 
Run Code Online (Sandbox Code Playgroud)

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

#ifdef TEST
    [[UIApplication sharedApplication] doAwesomeTestOnlyThing];
#endif 
Run Code Online (Sandbox Code Playgroud)

它不完全是运行时,但单元测试器在运行测试IIRC之前编译代码,因此它应该是相同的效果 - 您实际上是在运行测试之前修改代码.

  • 它可以工作,但它也仅限于使用测试编译的代码,例如目标应用程序代码不受影响(即您的应用程序委托没有定义宏).我解决这个问题的方法是复制DEBUG配置并在那里设置宏,然后编辑我的方案以在测试时使用这个新配置. (8认同)

Jon*_*eid 12

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

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

您可以在此处阅读有关此技术的更多信息:如何轻松切换您的iOS App代表以进行测试


Chu*_*k H 8

我不确定这将继续工作多久,但它现在适用于版本 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
    }
}()
Run Code Online (Sandbox Code Playgroud)

无需更改构建环境或方案。

根据您是运行单个测试用例还是整个测试套件,似乎有两个不同的环境变量在起作用。此外,变量值也因您是在模拟器中还是在真实设备上运行而异。


小智 6

我想你可以为Xcode 7.3这样检查

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