[英]What is the proper way to detect if unit tests are running at runtime in Xcode?
When I'm running unit tests, I'd like to skip some code (eg I don't want [[UIApplication sharedApplication] openURL:..]
to run). 当我运行单元测试时,我想跳过一些代码(例如我不希望
[[UIApplication sharedApplication] openURL:..]
运行)。 I'm looking for a runtime check if I'm currently running units tests or not. 我正在寻找运行时检查我是否正在运行单元测试。
I know I have seen code that checks the Objective-C runtime if unit tests are running but am not able to find it anymore. 我知道我已经看过代码检查Objective-C运行时,如果单元测试正在运行,但我再也找不到它了。
You can use this method from google-toolbox-for-mac 您可以使用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;
}
The reason that NSClassFromString
and NSInvocation
are used is to allow code compile without linking to xctest or ocunit 使用
NSClassFromString
和NSInvocation
的原因是允许代码编译而不链接到xctest或ocunit
Select the project, and then the test target: 选择项目,然后选择测试目标:
Select Build Settings and choose All and Combined. 选择Build Settings并选择All and Combined。 Type 'preproc' in the search box - you're after Preprocessor Macros.
在搜索框中键入“preproc” - 您在预处理器宏之后。
Add a macro to the Debug configuration called TEST
and set it equal to 1
: 将一个宏添加到名为
TEST
的Debug配置中,并将其设置为1
:
Then in your code, you can do this: 然后在您的代码中,您可以这样做:
#ifndef TEST
[[UIApplication sharedApplication] doEvilThingForTesting];
#endif
Or if you have code that you want to only run in a test environment: 或者,如果您希望只在测试环境中运行代码:
#ifdef TEST
[[UIApplication sharedApplication] doAwesomeTestOnlyThing];
#endif
It's not exactly runtime , but the unit tester compiles the code before it runs the tests IIRC, so it should be the same effect - you're essentially modifying the code right before running the tests. 它不完全是运行时 ,但单元测试器在运行测试IIRC之前编译代码,因此它应该是相同的效果 - 您实际上是在运行测试之前修改代码。
Rather that sprinkling "am I testing?" 而是洒“我在测试吗?” conditionals throughout production code, I isolate the check to one place:
main
. 在整个生产代码中的条件,我将支票隔离到一个地方:
main
。 There, I check for an alternate application delegate for testing. 在那里,我检查备用应用程序委托进行测试。 If it's available, I use it instead of the the regular application delegate.
如果它可用,我使用它而不是常规应用程序委托。 This completely bypasses the regular launch sequence:
这完全绕过了常规的启动顺序:
int main(int argc, char *argv[])
{
@autoreleasepool {
Class appDelegateClass = NSClassFromString(@"TestingAppDelegate");
if (!appDelegateClass)
appDelegateClass = [AppDelegate class];
return UIApplicationMain(argc, argv, nil, NSStringFromClass(appDelegateClass));
}
}
You can read more about this technique here: How to Easily Switch Your iOS App Delegate for Testing 您可以在此处阅读有关此技术的更多信息: 如何轻松切换您的iOS App代表以进行测试
I think you can check like this for Xcode 7.3 我想你可以为Xcode 7.3这样检查
-(BOOL) isRunningUnitTests
{
NSDictionary* environment = [ [ NSProcessInfo processInfo ] environment ];
NSString* theTestConfigPath = environment[ @"XCTestConfigurationFilePath" ];
return theTestConfigPath != nil;
}
I'm not sure how long this will continue to work, but it works for me right now with Version 9.0 beta 6 (9M214v). 我不知道这会持续多久,但它现在适用于版本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
}
}()
No build environment or scheme changes are necessary. 不需要构建环境或方案更改。
It appears that there are two different environment variables in play depending on whether you are running a single test case or the entire test suite. 根据您是运行单个测试用例还是整个测试套件,似乎有两个不同的环境变量在起作用。 Also, the variable value also differs depending whether or not you are running in simulator or on a real device.
此外,变量值也会有所不同,具体取决于您是在模拟器中还是在真实设备上运行。
The easiest (and working in Xcode 7 with XCTest!) way to check is to have a look at the process info for a matching xctest
bundle: 最简单的(并在Xcode 7中使用XCTest!)检查方法是查看匹配的
xctest
包的进程信息:
static BOOL isRunningTests(void)
{
NSDictionary* environment = [[NSProcessInfo processInfo] environment];
NSString* injectBundle = environment[@"XCInjectBundle"];
return [[injectBundle pathExtension] isEqualToString:@"xctest"];
}
Source: https://www.objc.io/issues/1-view-controllers/testing-view-controllers/#integration-with-xcode 资料来源: https : //www.objc.io/issues/1-view-controllers/testing-view-controllers/#integration-with-xcode
Just use this: 只要用这个:
+ (BOOL)isUnitTestRunning
{
Class testProbeClass;
testProbeClass = NSClassFromString(@"XCTestProbe");
return (testProbeClass != nil);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.