2016-05-17 27 views
7

Ho un'implementazione molto semplice XCTestCase che verifica un tocco su un pulsante e si aspetta che venga visualizzato un controller di avviso. Il problema è che il metodo tap() non funziona. Posizionando un punto di interruzione nell'IBAzione del pulsante associato, realizzo che la logica non viene nemmeno chiamata.XCUIElement tap() non funzionante

class uitestsampleUITests: XCTestCase { 

    var app: XCUIApplication! 

    override func setUp() { 
     super.setUp() 
     continueAfterFailure = false 
     app = XCUIApplication() 
     app.launch() 
    } 

    func testButton() { 
     let button = app.buttons["Button"] 
     button.tap() 

     expectationForPredicate(NSPredicate(format: "exists == 1"), evaluatedWithObject: button, handler: nil) 
     waitForExpectationsWithTimeout(5.0, handler: nil) 
    } 
} 

Inoltre, duplicando le istruzioni button.tap() rende il passaggio di prova, in questo modo:

func testButton() { 
     let button = app.buttons["Button"] 
     button.tap() 
     button.tap() 

     expectationForPredicate(NSPredicate(format: "exists == 1"), evaluatedWithObject: button, handler: nil) 
     waitForExpectationsWithTimeout(5.0, handler: nil)  
    } 

Sto affrontando questo problema in Xcode 7.3.1 Mi sto perdendo qualcosa? E 'un errore?

+1

Ho segnalato un bug ad Apple: https://openradar.appspot.com/26320475 –

+0

Potrebbe essere un problema di temporizzazione? Cosa succede quando aggiungi 1 sec di tempo di attesa prima di provare a toccare? Sfortunatamente, il framework di automazione dell'interfaccia utente, in particolare la generazione di eventi, è pieno di problemi. – Sulthan

+0

Non ho paura. Non funziona anche se aspetto questa aspettativa 'expectationForPredicate (NSPredicate (formato:" hittable == 1 "), valutatoWithObject: button, handler: nil)' –

risposta

8

Così un ingegnere di Apple ha risposto alla mia segnalazione dicendo:

La seconda possibilità è che si esegue in un problema che a volte si verifica quando l'applicazione termina lanciando ma lo schermo iniziale doesn scompaiono immediatamente e gli eventi inviati a l'app non vengono gestiti correttamente.

Per tentare di aggirare il problema, è consigliabile inserire un piccolo ritardo allo all'inizio del test (il sonno (1) dovrebbe essere sufficiente).

Così ho fatto e ora funziona:

override func setUp() { 
    super.setUp() 
    continueAfterFailure = false 
    app = XCUIApplication() 
    app.launch() 
    sleep(1) 
} 
+1

Per me il problema menzionato non è successo subito dopo il lancio dell'app. Ecco perché questa soluzione non coprirà tutti i casi. –

+0

hai risolto questo problema? Sto avendo lo stesso problema, se lo avessi risolto. –

1

Ho avuto qualcosa di simile. Per me il problema era che gli elementi, che ho provato a toccare, a volte non erano hittable per qualche motivo.

Dalla documentazione di Apple:

invia un evento rubinetto per un punto hittable calcolato per l'elemento.

Quindi, se un elemento non è hittable, l'azione di tocco non fa molto, il che interrompe la logica del test case.

Per risolvere il problema, prima di toccare qualcosa, attendo che l'elemento appropriato diventi hittable. Abbastanza diretto.

#import <XCTest/XCTest.h> 

@interface XCUIElement (Tap) 

- (void)tapInTestCase:(XCTestCase *)testCase; 

@end 

@implementation XCUIElement (Tap) 

- (void)tapInTestCase:(XCTestCase *)testCase 
{ 
    // wait until the element is hittable 
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"hittable == true"]; 
    [testCase expectationForPredicate:predicate evaluatedWithObject:element handler:nil]; 
    [testCase waitForExpectationsWithTimeout:5.0f handler:nil]; 

    // and then tap 
    [self tap]; 
} 

@end 
+0

Data la risposta che ho ricevuto da Apple, la soluzione potrebbe funzionare. Tuttavia nel campione di test molto semplice ho fornito che il pulsante è sempre lì, quindi non dovrebbe aspettare di essere "hittable" (il test dovrebbe iniziare quando l'interfaccia utente è pronta). Inoltre, la funzione Xcode di 'Record UI Test 'di Apple non inserisce codice per il pulsante in attesa di essere" hittable ". Preferisco aggiungere la soluzione 'sleep (1)' finché non risolvono questo problema. –

+0

Fantastico, sono felice che tu abbia una soluzione. Ma dovrei dire, è tutt'altro che perfetto. –

+1

Per me entrambe le soluzioni non funzionano sempre. A volte lo fanno, a volte no. Sto ancora cercando un modo per toccare il pulsante correttamente ... Ho anche un problema con 'typeText:' –

1

Per UIWebView che è hittable, il rubinetto non ha funzionato fino a quando l'ho fatto tramite coordinate:

extension XCUIElement { 
    func forceTap() { 
     coordinate(withNormalizedOffset: CGVector(dx:0.5, dy:0.5)).tap() 
    } 
} 

Spero che aiuti qualcuno

PS Funziona anche per oggetti che non sono percorribili, come etichette e simili.

+0

Ho dovuto usare questo quando stavo usando una vista che fluttua sopra lo schermo (scrollview in questo caso, anche se non so se è importante). Era visibile ed esisteva ma NON era percorribile, quindi tap() non funzionava. – sargturner