私は私のiOSプロジェクトにUIテストを組み込もうとしていますが、私が気を付け続けていることの1つは、作成するすべてのテストがアプリの最初から開始し、順調に進む必要があるという事実です。たとえば、ログイン画面の背後にあるビューをテストする場合、テストはまずログイン画面で実行し、ユーザー名/パスワードを入力して、[ログイン]をクリックしてから、テストするビューに移動する必要があります。ログインビューと次のビューのテストは完全に分離されるのが理想的です。これを行う方法はありますか、またはUIテストの背後にある哲学を完全に逃していますか?
絶対に!
必要なのは、テストを実行できるクリーンなアプリケーション環境、つまり白紙の状態です。
すべてのアプリケーションには、アプリケーションの初期状態を設定し、起動時にルートビューコントローラーを提供するアプリケーションデリゲートがあります。テストの目的では、それが起こらないようにしたいのですが、それらすべてが起こらずに、単独でテストできる必要があります。理想的には、画面をアンダーテストしてその画面のみをロードし、他の状態の変化は起こさないようにする必要があります。
そのためには、UIApplicationDelegate
を実装するテスト専用のオブジェクトを作成できます。 「テストモード」で実行するようにアプリケーションに指示し、起動引数を使用してテスト固有のアプリケーションデリゲートを使用できます。
Objective-C:main.m:
int main(int argc, char * argv[]) {
NSString * const kUITestingLaunchArgument = @"org.quellish.UITestingEnabled";
@autoreleasepool {
if ([[NSUserDefaults standardUserDefaults] valueForKey:kUITestingLaunchArgument] != nil){
return UIApplicationMain(argc, argv, nil, NSStringFromClass([TestingApplicationDelegate class]));
} else {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([ProductionApplicationDelegate class]));
}
}
}
Swift:main.Swift:
let kUITestingLaunchArgument = "org.quellish.UITestingEnabled"
if (NSUserDefaults.standardUserDefaults().valueForKey(kUITestingLaunchArgument) != nil){
UIApplicationMain(Process.argc, Process.unsafeArgv, NSStringFromClass(UIApplication), NSStringFromClass(TestingApplicationDelegate))
} else {
UIApplicationMain(Process.argc, Process.unsafeArgv, NSStringFromClass(UIApplication), NSStringFromClass(AppDelegate))
}
Swiftクラスから@UIApplicationMain
アノテーションを削除する必要があります。
「アプリケーションテスト」の場合は、スキームの「テスト」アクションをXcodeで設定して、起動引数を指定してください。
UIテストの場合、テストの一部として起動引数を設定できます。
Objective-C:
XCUIApplication *app = [[XCUIApplication alloc] init];
[app setLaunchArguments:@[@"org.quellish.UITestingEnabled"] ];
[app launch];
迅速:
let app = XCUIApplication()
app.launchArguments = [ "org.quellish.UITestingEnabled" ]
app.launch()
これにより、テストはアプリケーションデリゲートをテスト専用に使用できます。これにより、多くの制御が可能になります。これで、テストのために使用する空白のスレートができました。テストアプリケーションのデリゲートは、特定のストーリーボードを読み込むか、空のUIViewController
を配置できます。 UIテストの一部として、テスト対象のビューコントローラーをインスタンス化し、keyWindow
のルートビューコントローラーとして設定するか、モーダルで表示することができます。追加または表示されると、テストを実行できます。完了したら、削除または却下します。
元のUIの読み込みを気にしない場合は、次のコマンドでターゲットUIにジャンプします。
override func setUp() {
super.setUp()
continueAfterFailure = false
XCUIApplication().launch()
let storyboard = UIStoryboard(name: "MainStoryboard", bundle: NSBundle.mainBundle())
let controller = storyboard.instantiateViewControllerWithIdentifier("LanguageSelectController")
UIApplication.sharedApplication().keyWindow?.rootViewController = controller
}
下の元のUIをロードしたくない場合は、テストからこれも渡します。
app.launchArguments.append("skipEntryViewController")
didFinishLaunchingWithOptions
では、次のことを確認できます。
if NSProcessInfo.processInfo().arguments.contains("skipEntryViewController") {
// then do NOT call makeKeyAndVisible
}