[ios] 순수한 Swift 프로젝트에서 단위 테스트를 실행 중인지 앱에 알리는 방법은 무엇입니까?

Xcode 6.1에서 테스트를 실행할 때 한 가지 성가신 점은 전체 앱이 스토리 보드와 루트 뷰 컨트롤러를 실행하고 실행해야한다는 것입니다. 내 앱에서는 API 데이터를 가져 오는 서버 호출을 실행합니다. 그러나 테스트를 실행할 때 앱이이 작업을 수행하는 것을 원하지 않습니다.

전 처리기 매크로가 사라진 상태에서 내 프로젝트가 일반 실행이 아닌 테스트 실행 중임을 인식하는 가장 좋은 방법은 무엇입니까? command+ U와 봇에서 정상적으로 실행합니다 .

의사 코드 :

// Appdelegate.swift
if runningTests() {
   return
} else {
   // do ordinary api calls
}



답변

부작용을 피하기 위해 테스트가 실행 중인지 확인하는 대신 호스트 앱 자체없이 테스트를 실행할 수 있습니다. 프로젝트 설정으로 이동-> 테스트 대상 선택-> 일반-> 테스트-> 호스트 응용 프로그램-> ‘없음’을 선택합니다. 테스트를 실행하는 데 필요한 모든 파일과 일반적으로 Host 앱 대상에 포함 된 라이브러리를 포함해야합니다.

여기에 이미지 설명 입력


답변

Elvind의 대답은 순수 “Logic Tests”라고 불리는 것을 갖고 싶다면 나쁘지 않습니다. 포함 된 호스트 애플리케이션을 계속 실행하고 싶지만 테스트 실행 여부에 따라 조건부로 코드를 실행하거나 실행하지 않으려면 다음을 사용하여 테스트 번들이 삽입되었는지 감지 할 수 있습니다.

if NSProcessInfo.processInfo().environment["XCTestConfigurationFilePath"] != nil {
     // Code only executes when tests are running
}

런타임 비용이 디버그 빌드에서만 발생하도록 이 답변에 설명 대로 조건부 컴파일 플래그를 사용했습니다 .

#if DEBUG
    if NSProcessInfo.processInfo().environment["XCTestConfigurationFilePath"] != nil {
        // Code only executes when tests are running
    }
#endif

Swift 3.0 편집

if ProcessInfo.processInfo.environment["XCTestConfigurationFilePath"] != nil {
    // Code only executes when tests are running
}


답변

나는 이것을 application : didFinishLaunchingWithOptions에서 사용합니다.

// Return if this is a unit test
if let _ = NSClassFromString("XCTest") {
    return true
}


답변

기타, 내 생각에 더 간단한 방법 :

앱에 시작 인수로 부울 값을 전달하도록 스키마를 편집합니다. 이렇게 :

Xcode에서 시작 인수 설정

모든 시작 인수는 자동으로 NSUserDefaults .

이제 다음과 같이 BOOL을 얻을 수 있습니다.

BOOL test = [[NSUserDefaults standardUserDefaults] boolForKey:@"isTest"];


답변

테스트 내에서 실행 중인지 여부를 알고 싶은 것이 완전히 합법적이라고 생각합니다. 이것이 도움이 될 수있는 여러 가지 이유가 있습니다. 예를 들어 테스트를 실행할 때 App Delegate의 application-did / will-finish-launching 메서드에서 일찍 돌아와서 단위 테스트와 관련이없는 코드에 대해 테스트를 더 빠르게 시작합니다. 그러나 다른 여러 가지 이유로 순수한 “논리적”테스트를 수행 할 수 없습니다.

위의 @Michael McGuire가 설명한 뛰어난 기술을 사용했습니다. 그러나 Xcode 6.4 / iOS8.4.1에서 작동하지 않는 것으로 나타났습니다 (아마도 더 빨리 중단되었을 것입니다).

즉, 내 프레임 워크에 대한 테스트 대상 내에서 테스트를 실행할 때 더 이상 XCInjectBundle이 표시되지 않습니다. 즉, 프레임 워크를 테스트하는 테스트 대상 내에서 실행 중입니다.

따라서 @Fogmeister가 제안하는 접근 방식을 활용하여 각 테스트 체계는 이제 확인할 수있는 환경 변수를 설정합니다.

여기에 이미지 설명 입력

그런 다음 APPSTargetConfiguration이 간단한 질문에 답할 수있는 라는 클래스에 대한 몇 가지 코드 가 있습니다.

static NSNumber *__isRunningTests;

+ (BOOL)isRunningTests;
{
    if (!__isRunningTests) {
        NSDictionary *environment = [[NSProcessInfo processInfo] environment];
        NSString *isRunningTestsValue = environment[@"APPS_IS_RUNNING_TEST"];
        __isRunningTests = @([isRunningTestsValue isEqualToString:@"YES"]);
    }

    return [__isRunningTests boolValue];
}

이 접근 방식의 한 가지주의 사항은 XCTest에서 허용하는 것처럼 기본 앱 체계에서 테스트를 실행하면 (즉, 테스트 체계 중 하나를 선택하지 않음)이 환경 변수 집합을 얻지 못한다는 것입니다.


답변

var isRunningTests: Bool {
    return ProcessInfo.processInfo.environment["XCTestConfigurationFilePath"] != nil
}

용법

if isRunningTests {
    return "lena.bmp"
}
return "facebook_profile_photo.bmp"


답변

@Jessy와 @Michael McGuire의 결합 된 접근 방식

(허용되는 대답은 프레임 워크를 개발하는 동안 도움이되지 않습니다)

그래서 여기에 코드가 있습니다 :

#if DEBUG
        if (NSClassFromString(@"XCTest") == nil) {
            // Your code that shouldn't run under tests
        }
#else
        // unconditional Release version
#endif