2015-09-28 8 views
8

Ich habe versucht, HTTP-Anfragen in Xcode 7 automatisierten UI-Tests abzufangen und zu stub/mock, mit Tools wie OHHTTPStubs, ohne Glück.Ist es möglich, HTTP-Anfragen in automatisierten Xcode 7-UI-Tests zu stubben?

Hier ist ein Beispiel dafür, wie ich versuche, jede HTTP-Anforderung mit OHHTTPStubs im setUp Methode einer UI-Testdatei zu erfassen:

override func setUp() { 
    super.setUp() 

    let matcher: OHHTTPStubsTestBlock = { (request) -> Bool in 
    return true 
    } 

    OHHTTPStubs.stubRequestsPassingTest(matcher) { (response) -> OHHTTPStubsResponse! in 
    return OHHTTPStubsResponse.init() 
    } 
} 

Gibt es etwas über die Art und Weise, dass UI Testarbeiten, die dies verhindert? hat das jemand geschafft?

+0

Hey hast du mit einer Lösung am Ende? – MatterGoal

+0

Ja, nur unten hinzugefügt. – dtrenz

+0

Zum dynamischen HTTP-Anfragen Stummel Sie SBTUITestTunnel verwenden könnte, ist meine Antwort überprüfen [hier] (http://stackoverflow.com/a/36909859/574449) –

Antwort

8

Wie Martijn zu Recht darauf hingewiesen hat, können Sie zur Laufzeit nicht direkt mit der App interagieren, so dass sich HTTP-Spott oder Manipulation von Dingen wie NSUserDefaults in XCUITestCase nicht auf Ihre App auswirkt.

Wenn Sie wirklich HTTP oder Setup verspotten müssen in der Lage & Teardown Ihre Apps-Umgebung für bestimmte UI-Tests, müssen Sie Start Argumente festlegen oder Umgebungsvariablen starten, bevor die App in der setUp() Methode eines XCUITestCase starten und dann Ändern Sie Ihren App-Code, um die Startargumente oder Umgebungsvariablen zu lesen und die Testumgebung zu starten.

Beispiel Testcase

class MyTestCase: XCTestCase { 

    /** 
    Called before each test in this test case. 
    */ 
    override func setUp() { 
    super.setUp() 

     let app = XCUIApplication() 
     app.launchArguments = [ "STUB_HTTP_ENDPOINTS" ] 
     app.launch() 
    } 

} 

Beispiel AppDelegate

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 

#if DEBUG 
    if (NSProcessInfo.processInfo().arguments.contains("STUB_HTTP_ENDPOINTS")) { 
    // setup HTTP stubs for tests 
    } 
#endif 

    return true 
} 

Anmerkung: um einen HTTP zu verwenden Framework wie OHHTTPStubs in diesem Beispiel spöttischen, der Stubbing-Code und jeder JSON Fixtures, die Sie verwenden müssen, müssen alle in Ihrem App-Ziel sein, nicht das Testziel.

Dies ist ein sehr nützlicher Thread zu dem Thema zu lesen: https://github.com/AliSoftware/OHHTTPStubs/issues/124

+0

Es klingt wie, obwohl dies in der Tat ermöglichen wird, Stubbing zu erreichen, werden Sie auch eine App mit Stubbing "Code" und Stubbed-Netzwerk-Dateien innerhalb davon liefern. Was wahrscheinlich sehr schlecht ist. – Daniel

+0

Ich wickle den Stubbing-Code in eine if-Prüfung des DEBUG-Präprozessor-Makros ein, so dass der Stubbing-Code es nicht tatsächlich in den App Store-Build bringen sollte. Ich habe die Codebeispiele aktualisiert, um dies zu zeigen. Danke, dass du darauf hingewiesen hast. – dtrenz

3

UI-Tests werden in einer separaten Instanz von der Anwendung läuft. Während die Klassen aus der Anwendung möglicherweise für Sie verfügbar sind, sind sie nur eine Kopie.

In Ihrer Anwendung können Sie erkennen, ob Sie in UI-Test-Modus mit Lösungen, die hier bereitgestellt laufen: How to detect if iOS app is running in UI Testing mode

ich persönlich mit der launchEnvironment Lösung in der ursprünglichen Post erwähnt ging; Mein Setup sieht wie folgt aus:

override func setUp() { 
    super.setUp() 

    let app = XCUIApplication() 
    app.launchEnvironment["TEST"] = "1" 
    app.launch() 
} 

Und einer meiner Singleton instantiators (genannt RealmManager) sieht wie folgt aus (für eine Realm-Datenbank Instanziieren):

func realm() -> Realm { 
    let dic = NSProcessInfo.processInfo().environment 
    if dic["TEST"] != nil { 
     return try! Realm(configuration: Realm.Configuration(inMemoryIdentifier: "test")) 
    } 
    return try! Realm() 
} 

Wenn Sie die Vervielfältigung nicht mögen, aber Sie‘ re wahrscheinlich schon duplizieren XCUIApplication().launch() sowieso, können Sie immer eine benutzerdefinierte Testfall Klasse, die XCTestCase zu erweitern, überschreiben Sie die Setup dort mit diesem Zusatz und dann verwenden Sie das in allen Ihren Test-Klassen.

+0

Wie führen Sie verschiedene Testfälle?Wenn ich zum Beispiel den Login-Erfolg und den Login-Fehler testen möchte, wäre es die beste Vorgehensweise, die zwei verschiedenen Antworten zu stubben ... wie gehst du so mit deiner Logik um? Ich kann nur verstehen, wenn ich in "app realm" oder "test realm" laufe, aber ich kann nicht mit verschiedenen "Test Realm" -Antworten umgehen. – MatterGoal

+0

Gefälschte Benutzer? "user" + "wrongpassword" = fehlgeschlagen, "user" + "password" = Erfolg. –