UI Test Failure - Né l'elemento né alcun discendente ha il focus della tastiera su secureTextField


139

Questo è il mio caso:

let passwordSecureTextField = app.secureTextFields["password"]
passwordSecureTextField.tap()
passwordSecureTextField.typeText("wrong_password") //here is an error

UI Test Failure - Né l'elemento né alcun discendente ha lo stato attivo della tastiera. Elemento:

Che c'è? Funziona bene per il normale textFields, ma il problema sorge solo con secureTextFields. Qualche soluzione alternativa?



e la parte strana è che se provo in questo modo funziona XCUIApplication (). webViews.secureTextFields ["Password"]. tap () XCUIApplication (). webViews.secureTextFields ["Password"]. typeText ("Benvenuto")
aurilio

È possibile che tu abbia impostato l'identificatore di accessibilità ma non hai impostato isAccessibilityElement = true
soumil

Ho aggiunto una risposta a una domanda simile qui: stackoverflow.com/a/59637897/2585413 . Il mio problema era che avevo altre UIWindows con valori di .windowLevel non validi
nteissler

Risposte:


264

Questo problema mi ha causato un mondo di dolore, ma sono riuscito a trovare una soluzione adeguata. Nel simulatore, assicurati che "Hardware -> Tastiera -> Connetti tastiera hardware" sia spento.


4
Questo ha risolto il problema. Ma è una soluzione molto scadente in quanto non possiamo applicarla automaticamente per CI.
Stanislav Pankevich,

25
Se si eseguono i test su CI (Jenkins ecc.) È possibile impostare i seguenti parametri in uno script prima di eseguire i test. "defaults write com.apple.iphonesimulator ConnectHardwareKeyboard 0"
charlyatwork

7
Questo non risolve il problema per me. Riesco a vedere chiaramente che il campo di testo sta diventando attivo, con la tastiera in alto, ma il framework di test non può mai inserire testo usando il tipoTesto: metodo
Michael

2
Ha funzionato per me su Xcode 11, ma deselezionare la tastiera hardware Connect potrebbe non essere sufficiente. Uno deve inoltre garantire che la tastiera del software sia realmente mostrata (in realtà avevo la situazione in cui non era collegata nessuna tastiera hardware e nessuna tastiera software era mostrata, anche se textField era attivo e il cursore lampeggiava).
Reinhard Männer,

1
Mi sono imbattuto in questo anche su Xcode 11. Risolve localmente, ma come può essere impostato in CI?
jherg

26

Recentemente abbiamo trovato un hack per rendere persistente la soluzione dalla risposta accettata. Per disabilitare le impostazioni del simulatore: 'Hardware -> Tastiera -> Collega tastiera hardware' dalla riga di comando si dovrebbe scrivere:

defaults write com.apple.iphonesimulator ConnectHardwareKeyboard 0

Non influirà su un simulatore in esecuzione: è necessario riavviare il simulatore o avviarne uno nuovo per rendere effettiva tale impostazione.


questo non ha cambiato qualcosa.
netshark1000,

@ netshark1000 che potrebbe essere modificato con la versione più recente di Xcode, lo controllerò.
AlexDenisov,

1
estremamente utile, avevo bisogno del contrario dove la tastiera è sempre abilitata, ma sì, questo è fantastico grazie. Ho finito per andare avanti defaults write com.apple.iphonesimulator ConnectHardwareKeyboard -bool true, ma è lo stesso concetto.
Laser Hawk,

2
Ho creato uno script sulle fasi di compilazione per farlo. Ma dovevo uccidere tutti i simulatori, quindi l'ho fatto:killall "Simulator"; defaults write com.apple.iphonesimulator ConnectHardwareKeyboard 0;
Wagner Sales,

Questo non sembra funzionare più, la chiave è cambiata ?? @AlexDenisov
Simon McLoughlin,

15

Ho scritto una piccola estensione (Swift) che funziona perfettamente per me. Ecco il codice:

extension XCTestCase {

    func tapElementAndWaitForKeyboardToAppear(element: XCUIElement) {
        let keyboard = XCUIApplication().keyboards.element
        while (true) {
            element.tap()
            if keyboard.exists {
                break;
            }
            NSRunLoop.currentRunLoop().runUntilDate(NSDate(timeIntervalSinceNow: 0.5))
        }
    }
}

L'idea principale è quella di continuare a toccare un elemento (campo di testo) prima che venga presentata la tastiera.


Questo non funziona per me in questo momento. Sto avendo Xcode 7.2 (7C68), che versione hai? Questa soluzione che abbiamo trovato per CI funziona per noi: stackoverflow.com/a/34812979/598057 .
Stanislav Pankevich,

Per confermarlo ancora una volta: questo aiuto funziona per te nel campo di testo sicuro della password, non solo nel normale campo di testo?
Stanislav Pankevich,

Sì, funziona per entrambi i tipi di campo di testo: normale e sicuro.
berezhnyi oleksandr,

1
Il problema con questa risposta è che utilizza un ritardo hardcoded. Invece, usa l'attesa per il modello aspettative con l'elemento tastiera.
user1122069

11

Stanislav ha l'idea giusta.

In un ambiente di squadra, è necessario qualcosa che funzioni automaticamente. Ho trovato una soluzione qui sul mio blog.

Fondamentalmente basta incollare:

UIPasteboard.generalPasteboard().string = "Their password"
let passwordSecureTextField = app.secureTextFields["password"]
passwordSecureTextField.pressForDuration(1.1)
app.menuItems["Paste"].tap()

Grazie per aver condiviso la tua soluzione. Sfortunatamente non funziona per me in questo momento. Sto avendo Xcode 7.2 (7C68), che cosa? Guarda l'altra soluzione che abbiamo trovato per CI: stackoverflow.com/questions/32184837/… .
Stanislav Pankevich,

8

Un'altra causa di questo errore è se esiste una vista principale del campo di testo in cui si sta tentando di inserire un testo impostato come elemento di accessibilità ( view.isAccessibilityElement = true). In questo caso, XCTest non è in grado di ottenere un handle sulla vista secondaria per inserire il testo e restituire l'errore.

UI Test Failure - Né l'elemento né alcun discendente ha lo stato attivo della tastiera.

Non è che nessun elemento abbia lo stato attivo (come spesso puoi vedere la tastiera in su e il cursore lampeggiante in UITextField), è solo che nessun elemento che può raggiungere ha lo stato attivo . Mi sono imbattuto in questo durante il tentativo di inserire il testo in un UISearchBar. La barra di ricerca stessa non è il campo di testo, quando lo si imposta come elemento di accessibilità, l'accesso all'UITextField sottostante è stato bloccato. Per risolvere questo problema, è searchBar.accessibilityIdentifier = "My Identifier"stato impostato su UISearchBartuttavia isAccessibilityElementnon è stato impostato su true. Successivamente, verifica il codice del modulo:

app.otherElements["My Identifier"].tap()
app.otherElements["My Identifier"].typeText("sample text")

Lavori


6

È successo con me per molte volte. È necessario disabilitare l'hardware della tastiera e lo stesso layout dell'OSX nel simulatore

Hardware / tastiera (disabilita tutto)

Dopodiché il software della tastiera non si chiuderà e i test potranno digitare il testo

Disabilita hardware


5

Usa una pausa tra l'avvio dell'app e la digitazione dei dati in campi di testo come questo:

sleep(2)

Nel mio caso continuavo a ricevere questo errore ogni volta e solo questa soluzione mi ha aiutato.


1
Il problema è che se hai un gran numero di test dell'interfaccia utente che eseguono qualcosa di simile a un accesso iniziale, questo aggiungerà un enorme sovraccarico alla tua esecuzione di test CI.
delta2flat,

4

Questo forse aiuta: aggiungo semplicemente un'azione "tocca" prima dell'errore; È tutto :)

[app.textFields[@"theTitle"] tap];
[app.textFields[@"theTitle"] typeText:@"kk"];

2
Questo sicuramente non funziona per il campo di testo della password sicura.
Stanislav Pankevich,

Questo ha funzionato bene per il mio campo di testo della password sicura. Buona soluzione
Travis M.,

4
func pasteTextFieldText(app:XCUIApplication, element:XCUIElement, value:String, clearText:Bool) {
    // Get the password into the pasteboard buffer
    UIPasteboard.generalPasteboard().string = value

    // Bring up the popup menu on the password field
    element.tap()

    if clearText {
        element.buttons["Clear text"].tap()
    }

    element.doubleTap()

    // Tap the Paste button to input the password
    app.menuItems["Paste"].tap()
}

4

Registra la custodia come preferisci, tastiera o senza tastiera collegata. Prima di fare il test, fai quanto segue.

Questa opzione seguente (collegare la tastiera hardware) deve essere deselezionata durante l'esecuzione del test.

inserisci qui la descrizione dell'immagine


4

Nel mio caso questo Hardware -> Keyboard -> Connect Hardware Keyboard-> Disabilita non ha funzionato per me.

Ma quando l'ho seguito

1) Hardware -> Keyboard -> Connect Hardware Keyboard-> Abilitato ed esegui l'app
2) Hardware -> Keyboard -> Connect Hardware Keyboard-> Disabilita .

Ha funzionato per me


Ha funzionato per me, UOMO Odio questo aspetto di XCode!
bwobbones,

3

[ Ripubblicando il commento di Bartłomiej Semańczyk come risposta perché ha risolto il problema per me]

Avevo bisogno di fare Simulator> Ripristina contenuti e impostazioni nella barra dei menu del simulatore per iniziare a lavorare per me.


Anche il ripristino del simulatore mi ha aiutato. È interessante notare che il problema si è verificato solo nel simulatore mentre lo stesso test (toccare texfield seguito da caratteri digitati) ha funzionato bene su un dispositivo.
Christian,

1

A volte i campi di testo non sono implementati come campi di testo o sono inseriti in un altro elemento dell'interfaccia utente e non sono facilmente accessibili. Ecco una soluzione:

//XCUIApplication().scrollViews.otherElements.staticTexts["Email"] the locator for the element
RegistrationScreenStep1of2.emailTextField.tap()
let keys = app.keys
 keys["p"].tap() //type the keys that you need
 
 //If you stored your data somewhere and need to access that string //you can cats your string to an array and then pass the index //number to key[]
 
 let newUserEmail = Array(newPatient.email())
 let password = Array(newPatient.password)
 
 //When you cast your string to an array the elements of the array //are Character so you would need to cast them into string otherwise //Xcode will compain. 
 
 let keys = app.keys
     keys[String(newUserEmail[0])].tap()
     keys[String(newUserEmail[1])].tap()
     keys[String(newUserEmail[2])].tap()
     keys[String(newUserEmail[3])].tap()
     keys[String(newUserEmail[4])].tap()
     keys[String(newUserEmail[5])].tap()       


0

La tua prima riga è solo una definizione di query , il che non significa chepasswordSecureTextField esisterebbe effettivamente.

La seconda riga eseguirà dinamicamente la query e proverà a (ri) associare la query all'elemento dell'interfaccia utente. Dovresti inserire un punto di interruzione su di esso e verificare che sia stato trovato un solo elemento. O semplicemente usa un'asserzione:

XCTAssertFalse(passwordSecureTextField.exists);

Altrimenti sembra ok, tapdovrebbe forzare la tastiera visibile e quindi typeTextdovrebbe funzionare. Il registro degli errori dovrebbe dirti ulteriori informazioni.


1
passwordSecureTextFieldesiste. Ho risolto il problema, ma pulendo la memoria e riscrivendo quelle righe. Strano, ma ha funzionato.
Bartłomiej Semańczyk,

È bello sapere che è stato risolto! Mi sono imbattuto in un problema simile ieri con la beta 6 :)
JOM il

beta 6? :-) davvero? Ne ho solo 5 :)
Bartłomiej Semańczyk il

Sei stato impegnato a tapscrivere codice :) Beta 6 non ha registrato per me, ci è voluto del tempo per capirlo. Buona pratica di debug!
JOM,

Forse conosci la risposta per questo: stackoverflow.com/questions/32219015/… ?
Bartłomiej Semańczyk,

0

Non fare casini, c'è un problema colto perché il tuo tempo di test è stato registrato e la tua app collegherà la tastiera hardware mentre il simulatore del tempo di test automatico impiega solo la tastiera del software. quindi per come risolvere questo problema. Basta usare la tastiera del software sul tempo di registrazione. puoi vedere la magia.


0

Il problema per me era lo stesso di Ted. In realtà se il campo della password viene toccato dopo il campo di accesso e l'hardware KB è attivo, la tastiera del software si chiuderà automaticamente al secondo tocco del campo e non è specifica per i test dell'interfaccia utente.

Dopo un po 'di tempo con AppleScript, ecco cosa mi è venuto in mente (i miglioramenti sono ben accetti):

tell application "Simulator" activate tell application "System Events" try tell process "Simulator" tell menu bar 1 tell menu bar item "Hardware" tell menu "Hardware" tell menu item "Keyboard" tell menu "Keyboard" set menuItem to menu item "Connect Hardware Keyboard" tell menu item "Connect Hardware Keyboard" set checkboxStatus to value of attribute "AXMenuItemMarkChar" of menuItem if checkboxStatus is equal to "✓" then click end if end tell end tell end tell end tell end tell end tell end tell on error tell application "System Preferences" activate set securityPane to pane id "com.apple.preference.security" tell securityPane to reveal anchor "Privacy_Accessibility" display dialog "Xcode needs Universal access to disable hardware keyboard during tests(otherwise tests may fail because of focus issues)" end tell end try end tell end tell

Crea un file di script con il codice sopra e aggiungilo ai target necessari (probabilmente solo test dei test dell'interfaccia utente, potresti voler aggiungere uno script simile ai target di sviluppo per riattivare la tastiera HW durante lo sviluppo). È necessario aggiungere una Run Scriptfase nelle fasi di creazione e utilizzarla in questo modo: osascript Path/To/Script/script_name.applescript


0

Si è verificato lo stesso errore durante l'impostazione del accessibilityIdentifiervalore per una vista personalizzata ( UIStackViewsottoclasse) contenente UIControlviste secondarie. In tal caso XCTest non è stato in grado di ottenere lo stato attivo della tastiera per gli elementi discendenti.

La nostra soluzione era semplicemente quella di rimuovere il accessibilityIdentifierdalla vista del genitore e impostare il accessibilityIdentifierper le viste secondarie attraverso proprietà dedicate.


0

Un'altra risposta, ma per noi il problema era che la vista era troppo vicina a un'altra vista che un riconoscitore di gesti su di esso. Abbiamo scoperto che la vista doveva essere distante almeno 20 pixel (nel nostro caso di seguito). Letteralmente 15 non hanno funzionato e 20 o più hanno funzionato. Questo è strano, lo ammetto, ma avevamo alcune UITextViews che funzionavano e alcune che non erano e tutte erano sotto lo stesso genitore e identici altri posizionamenti (e ovviamente nomi variabili). La tastiera accesa o spenta o qualsiasi altra cosa non ha fatto differenza. L'accessibilità ha mostrato i campi. Abbiamo riavviato i nostri computer. Abbiamo fatto build pulite. Checkout originali.


0

Ciò che ha risolto questo problema per me è stato l'aggiunta di un sonno di 1 secondo:

let textField = app.textFields["identifier"]
textField.tap()
sleep(1)
textField.typeText(text)

0

Ho riscontrato questo problema e sono stato in grado di risolverlo nel mio scenario prendendo la soluzione pubblicata da @AlexDenisov e aggiungendola alle mie azioni preliminari per l' esecuzione e il test .

inserisci qui la descrizione dell'immagine


0

Non è necessario attivare / disattivare la tastiera in I / O. Non usare .typeText per secureTextField, basta usare

app.keys["p"].tap()
app.keys["a"].tap()
app.keys["s"].tap()
app.keys["s"].tap()

Bonus: ottieni il suono della tastiera fai clic :)


0

Infine, ho scritto uno script che modifica il file .plist del simulatore e imposta il file ConnectHardwareKeyboard proprietà su false per il simulatore selezionato. Hai sentito bene, cambia la proprietà per il simulatore appositamente selezionato all'interno del dizionario "DevicePreferences" anziché modificare la proprietà globale.

Innanzitutto, crea uno script shell chiamato disable-hardware-keyboard.sh con i seguenti contenuti. Puoi inserirlo in "YourProject / xyzUITests / Scripts /" .:

echo "Script: Set ConnectHardwareKeyboard to false for given Simulator UDID"

if [[ $1 != *-*-*-*-* ]]; then
    echo "Pass device udid as first argument."
    exit 1
else
    DEVICE_ID=$1
fi

DEVICE_PREFERENCES_VALUE='<dict><key>ConnectHardwareKeyboard</key><false/></dict>'
killall Simulator # kill restart the simulator to make the plist changes picked up
defaults write com.apple.iphonesimulator DevicePreferences -dict-add $DEVICE_ID $DEVICE_PREFERENCES_VALUE
open -a Simulator # IMPORTANT

Ora segui questi passaggi per chiamarlo con il passaggio dell'udid del simulatore selezionato come argomento:

  1. Modifica lo schema Xcode (o lo schema specifico dei test dell'interfaccia utente se ne hai uno)
  2. Vai a: Test> Pre-azioni
  3. Aggiungi nuovo script toccando il simbolo "+"> "Nuova azione script di esecuzione".
  4. Importante: all'interno del menu a discesa "Fornisci impostazioni di build da" scegli il target dell'app principale, non il target dei test dell'interfaccia utente.
  5. Ora aggiungi il seguente script nell'area di testo qui sotto.

Script all'interno di Test> Pre-azioni:

#!/bin/sh
# $PROJECT_DIR is path to your source project. This is provided when we select "Provide build settings from" to "AppTarget"
# $TARGET_DEVICE_IDENTIFIER is the UDID of the selected simulator
sh $PROJECT_DIR/xyzUITests/Scripts/disable-hardware-keyboard.sh $TARGET_DEVICE_IDENTIFIER

# In order to see output of above script, append following with it:
#  | tee ~/Desktop/ui-test-scheme-prescript.txt

Tempo di testarlo:

  1. Avvia il simulatore
  2. Abilita la tastiera hardware per questo
  3. Esegui qualsiasi test dell'interfaccia utente con l'interazione da tastiera. Osservare il riavvio del simulatore e la tastiera hardware è disabilitata. E l'interazione della tastiera del test funziona bene. :)

-1

Ha avuto lo stesso problema con Securetextfields. L'opzione di connessione hardware nel mio simulatore era di, ma continuava a riscontrare il problema. Alla fine, questo ha funzionato per me (Swift 3):

 let enterPasswordSecureTextField = app.secureTextFields["Enter Password"]
    enterPasswordSecureTextField.tap()
    enterPasswordSecureTextField.typeText("12345678")

Qual è la differenza tra il codice e il codice richiesto nella domanda.
Shivam Pokhriyal,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.