Каков надлежащий способ определения, выполняются ли во время выполнения в Xcode аппаратные тесты?
Когда я запускаю модульные тесты, я бы хотел пропустить некоторый код (например, я не хочу, чтобы [[UIApplication sharedApplication] openURL:..]
запускался). Я ищу проверку времени выполнения, если я в настоящее время выполняю тесты модулей или нет.
Я знаю, что видел код, который проверяет время выполнения Objective-C, если юнит-тесты запущены, но я больше не могу его найти.
Ответы
Ответ 1
Вы можете использовать этот метод из 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
Ответ 2
Выберите проект, а затем цель тестирования:
![enter image description here]()
Выберите "Настройки сборки" и выберите "Все" и "Комбинировать". Введите "preproc" в поле поиска - вы выполняете макросы препроцессора.
![enter image description here]()
Добавьте макрос в конфигурацию Debug с именем TEST
и установите его равным 1
:
![enter image description here]()
Затем в вашем коде вы можете сделать это:
#ifndef TEST
[[UIApplication sharedApplication] doEvilThingForTesting];
#endif
Или если у вас есть код, который вы хотите запускать только в тестовой среде:
#ifdef TEST
[[UIApplication sharedApplication] doAwesomeTestOnlyThing];
#endif
Это не совсем время исполнения, но тестер модулей компилирует код, прежде чем он запускает тесты IIRC, поэтому он должен быть тем же самым эффектом - вы существенно модифицируете код перед запуском тестов.
Ответ 3
Скорее, что посыпать "я тестирую?" условные обозначения во всем производственном коде, я изолирую чек в одном месте: main
. Там я проверяю альтернативный делегат приложения для тестирования. Если он доступен, я использую его вместо обычного делегата приложения. Это полностью обходит обычную последовательность запуска:
int main(int argc, char *argv[])
{
@autoreleasepool {
Class appDelegateClass = NSClassFromString(@"TestingAppDelegate");
if (!appDelegateClass)
appDelegateClass = [AppDelegate class];
return UIApplicationMain(argc, argv, nil, NSStringFromClass(appDelegateClass));
}
}
Подробнее об этом методе вы можете прочитать здесь: http://qualitycoding.org/app-delegate-for-tests/
Ответ 4
Я думаю, что вы можете проверить это для Xcode 7.3
-(BOOL) isRunningUnitTests
{
NSDictionary* environment = [ [ NSProcessInfo processInfo ] environment ];
NSString* theTestConfigPath = environment[ @"XCTestConfigurationFilePath" ];
return theTestConfigPath != nil;
}
Ответ 5
Самый простой (и работающий в 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
Ответ 6
Я не уверен, как долго это будет продолжаться, но оно работает для меня прямо сейчас с версией 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
}
}()
Не требуется никаких изменений среды сборки или схемы.
Похоже, что в игре есть две разные переменные среды, в зависимости от того, используете ли вы один тестовый пример или весь комплект тестов. Кроме того, значение переменной также зависит от того, работаете ли вы в симуляторе или на реальном устройстве.
Ответ 7
Просто используйте это:
+ (BOOL)isUnitTestRunning
{
Class testProbeClass;
testProbeClass = NSClassFromString(@"XCTestProbe");
return (testProbeClass != nil);
}