2015-12-17 22 views
25

私はiOSプロジェクトにUIテストを組み込もうとしていますが、あなたが書いたテストのすべてが最初から始まる必要があります。アプリとその方法を介して動作します。たとえば、ログイン画面の背後にあるビューをテストする場合は、まずログイン画面でテストを実行し、ユーザー名とパスワードを入力してログインをクリックしてから、テストするビューに移動する必要があります。理想的には、ログインビューと次のテストのテストは完全に分離されています。これを行う方法はありますか、またはUIテストの背後にある考え方を完全に欠いていますか?iOSのUIテスト(隔離されたビュー)

+0

をly:アプリはクリーンで始まり、テストコードはVCの提示方法を決め、テストコードはオートメーションを使用してUIとやりとりします。これはUIユニットテストです。このトピックに関する私の研究はすべて、https://gist.github.com/fulldecent/529849bc5dd4464bbde2です。多分、他の誰かがトーチを手に入れることができます。 –

答えて

-1

残念ながら、UIテストでは、あなたが記述したシナリオは不可能です。

私がこれに対処する方法の1つは、テストを機能の「フロー」にグループ化することです。たとえば、フィーチャーA、フィーチャーB、フィーチャーCをテストしたいとします。3つすべてを動作させるには、ログインする必要があります。

私はアプリを起動しないでログインし、最後に実際のテストを実行します。代わりに、私はアプリを起動し、一度ログインします。次に私のテストを3つのプライベートヘルパーメソッド、testFeatureA()testFeatureB()、およびtestFeatureC()に分類します。

フローを1つ作成することで、テストスイートの実行時間が大幅に短縮されます。大きな欠点は、フィーチャーAが失敗した場合、フィーチャーBは決してテストされないということです。このアプローチは、すべてののテストが合格するかどうかを気にする場合にのみ使用してください。

XCTest helper__LINE____FILE__パラメータをデフォルトで使用するためのボーナスポイント。その後、あなたのXCTFail()コールにそれらを渡して、testFeatureA()の失敗ラインを表示することができます。

+0

実際に可能な限り下降しました(クェリッシュ回答を参照) –

19

絶対に!

必要なのは、テストを実行できるクリーンなアプリケーション環境です。空白のスレートです。

すべてのアプリケーションには、アプリケーションの初期状態を設定し、起動時にルートビューコントローラを提供するアプリケーションデリゲートがあります。テスト目的のためには、そのようなことが起こらないように、孤立してテストできる必要があります。理想的には、画面をアンテストし、その画面のみをロードし、他の状態の変更は起こらないようにしたいと考えています。

これを行うには、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])); 
     } 
    } 
} 

スウィフト: 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)) 
} 

あなたのスウィフトのクラスから任意の@UIApplicationMain注釈を削除する必要があります。「アプリケーションのテスト」については

は、起動引数を提供するために、Xcodeでのスキームの「テスト」アクションを設定してください:UIテスト用の

Xcode Scheme editor

あなたはの一環として立ち上げ引数を設定することができます試験:

のObjective-C:

XCUIApplication *app = [[XCUIApplication alloc] init]; 
[app setLaunchArguments:@[@"org.quellish.UITestingEnabled"] ]; 
[app launch]; 

スウィフト:

これにより、テストではテスト用にアプリケーションデリゲートを使用することができます。これにより、多くの制御が可能になります。テストのために作業するための空白があります。テストアプリケーションデリゲートは、特定のストーリーボードをロードしたり、空のUIViewControllerを配置したりすることができます。 UIテストの一環として、テスト中のView Controllerをインスタンス化し、keyWindowのルートビューコントローラとして設定するか、モーダルで表示することができます。追加または提示されると、テストが実行され、完了したら削除または却下されます。

+4

この解決策は本当に素晴らしいようです!しかし、 'NSUserDefaults.standardUserDefaults()。valueForKey(kUITestingLaunchArgument)!= nil'は私のために働いていませんでした。 NSProcessInfo.processInfo()。arguments.contains(kUITestingLaunchArgument)に変更して動作させました。 –

+0

@FyodorVolchyok私は、ユーザーのデフォルトが機能するはずだから、レーダーを提出することを強くお勧めします。起動引数は、引数ドメインと同じように他のデフォルトに優先します。 – quellish

+0

@quellishテストでUIStoryboardを簡単に読み込むことはできません(あなたのポストのようにプライベートvarを公開しない限り)http://quellish.tumblr.com/post/135415677047/ios-application-and-ui-testing-in-isolation )。私がやることは、追加の引数を使うことです。そのため、TestAppDelegateはUIStoryboardとUIViewControllerをインスタンス化することを知っています。 –

4

あなたは、元の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 
} 
+0

問題は、必要なものがきれいで分離されたテストであることを指定していますが、これはそうではありません。 –

+0

どのようにその要件を満たしていませんか? –

+0

同じアプリケーションデリゲートと元のUI読み込みを維持すると、干渉する可能性のある作業が行われることがあります。 –

関連する問題