web-dev-qa-db-ja.com

Xcodeでユニットテストが実行時に実行されているかどうかを検出する適切な方法は何ですか?

単体テストを実行しているときに、一部のコードをスキップしたい(たとえば、[[UIApplication sharedApplication] openURL:..]を実行したくない)。現在ユニットテストを実行しているかどうかのランタイムチェックを探しています。

単体テストが実行されている場合にObjective-Cランタイムをチェックするコードを見たことがありますが、それを見つけることができなくなりました。

18
Ronald Mannak

このメソッド from 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にリンクせずにコードをコンパイルできるようにするためです。

17
Bryan Chen

むしろ、「私はテストしていますか?」本番コード全体の条件文で、チェックを1つの場所(main)に分離します。そこで、テスト用にalternateアプリケーションデリゲートをチェックします。利用可能な場合は、通常のアプリケーションデリゲートの代わりに使用します。これにより、通常の起動シーケンスが完全にバイパスされます。

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

この手法の詳細については、こちらをご覧ください: iOSアプリのデリゲートをテスト用に簡単に切り替える方法

13
Jon Reid

プロジェクトを選択してから、テストターゲットを選択します。

enter image description here

[ビルド設定]を選択し、[すべて]と[結合]を選択します。検索ボックスに「preproc」と入力します。プリプロセッサマクロを探しています。

enter image description here

TESTという名前のマクロをデバッグ構成に追加し、それを1と等しく設定します。

enter image description here

次に、コードでこれを行うことができます。

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

または、テスト環境で実行したいコードがある場合のみ

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

正確にはruntimeではありませんが、単体テスターはテストIIRCを実行する前にコードをコンパイルするため、同じ効果が得られるはずです。基本的に、テストを実行する直前にコードを変更します。

11
Undo

Xcode7.3についてはこのように確認できると思います

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

確認する最も簡単な(そして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

2
Gavin Bunney

これを使用するだけです:

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