[英]What is the proper way to detect if unit tests are running at runtime in Xcode?
当我运行单元测试时,我想跳过一些代码(例如我不希望[[UIApplication sharedApplication] openURL:..]
运行)。 我正在寻找运行时检查我是否正在运行单元测试。
我知道我已经看过代码检查Objective-C运行时,如果单元测试正在运行,但我再也找不到它了。
您可以使用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;
}
使用NSClassFromString
和NSInvocation
的原因是允许代码编译而不链接到xctest或ocunit
选择项目,然后选择测试目标:
选择Build Settings并选择All and Combined。 在搜索框中键入“preproc” - 您在预处理器宏之后。
将一个宏添加到名为TEST
的Debug配置中,并将其设置为1
:
然后在您的代码中,您可以这样做:
#ifndef TEST
[[UIApplication sharedApplication] doEvilThingForTesting];
#endif
或者,如果您希望只在测试环境中运行代码:
#ifdef TEST
[[UIApplication sharedApplication] doAwesomeTestOnlyThing];
#endif
它不完全是运行时 ,但单元测试器在运行测试IIRC之前编译代码,因此它应该是相同的效果 - 您实际上是在运行测试之前修改代码。
而是洒“我在测试吗?” 在整个生产代码中的条件,我将支票隔离到一个地方: main
。 在那里,我检查备用应用程序委托进行测试。 如果它可用,我使用它而不是常规应用程序委托。 这完全绕过了常规的启动顺序:
int main(int argc, char *argv[])
{
@autoreleasepool {
Class appDelegateClass = NSClassFromString(@"TestingAppDelegate");
if (!appDelegateClass)
appDelegateClass = [AppDelegate class];
return UIApplicationMain(argc, argv, nil, NSStringFromClass(appDelegateClass));
}
}
您可以在此处阅读有关此技术的更多信息: 如何轻松切换您的iOS App代表以进行测试
我想你可以为Xcode 7.3这样检查
-(BOOL) isRunningUnitTests
{
NSDictionary* environment = [ [ NSProcessInfo processInfo ] environment ];
NSString* theTestConfigPath = environment[ @"XCTestConfigurationFilePath" ];
return theTestConfigPath != nil;
}
我不知道这会持续多久,但它现在适用于版本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
}
}()
不需要构建环境或方案更改。
根据您是运行单个测试用例还是整个测试套件,似乎有两个不同的环境变量在起作用。 此外,变量值也会有所不同,具体取决于您是在模拟器中还是在真实设备上运行。
最简单的(并在Xcode 7中使用XCTest!)检查方法是查看匹配的xctest
包的进程信息:
static BOOL isRunningTests(void)
{
NSDictionary* environment = [[NSProcessInfo processInfo] environment];
NSString* injectBundle = environment[@"XCInjectBundle"];
return [[injectBundle pathExtension] isEqualToString:@"xctest"];
}
资料来源: https : //www.objc.io/issues/1-view-controllers/testing-view-controllers/#integration-with-xcode
只要用这个:
+ (BOOL)isUnitTestRunning
{
Class testProbeClass;
testProbeClass = NSClassFromString(@"XCTestProbe");
return (testProbeClass != nil);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.