LoginSignup
30
16

More than 3 years have passed since last update.

[Swift] テストの実行時にプロダクトコードを実行しないようにする

Last updated at Posted at 2016-08-21

テストを書いて、XCTest を実行してみるとユニットテスト以外にもアプリが起動しますよね。

他の言語のユニットテストフレームワークだとそんなことはないのですが、XCTest の場合テスト実行とともに application(application:didFinishLaunchingWithOptions) が呼ばれます。

テスト実行時にアプリの起動時のコードも実行されると無駄なログが発生したり、テストを正しく実行できません。

テスト実行中かどうかを判定する

テストの実行中かどうかはテストの実行環境にのみ存在する Class があるかどうかで判定できます。
テストの実行環境にのみ存在する Class とは XCTest Class などがあります。

    func isTesting() -> Bool {
        return NSClassFromString("XCTest") != nil // nil じゃなかったらテスト実行中
    }

2016/08/21 23:48追記

※これはXcode7まで
@mono0926 さんからコメントいただきました。↑の例とは別に判定する方法があるそうです。

    func isTesting() -> Bool {
        return NSProcessInfo.processInfo().environment["XCInjectBundle"] != nil
    }

2016/10/28 23:38追記

ProcessInfoを使う場合 Xcode8 から判別方法が変わったようです。

    func isTesting() -> Bool {
        return ProcessInfo.processInfo.environment["XCTestConfigurationFilePath"] != nil
    }

テスト実行中の場合処理をスキップする

この判定を application(application:didFinishLaunchingWithOptions) の先頭において、もしテスト中だと何もしないコードを入れます。本番環境に(テスト専用の)不要なコードが入るのはイヤなので #if DEBUG など、リリース時にはコードが含まれないようにするといいと思います。

class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        #if DEBUG
        guard !isTesting() else { // テスト実行中なら
            window?.rootViewController = UIViewController()
            return true
        }
        #endif
    }
}

extension AppDelegate {
    func isTesting() -> Bool {
        return NSClassFromString("XCTest") != nil
    }
}
30
16
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
30
16