C'est mon cas:
let passwordSecureTextField = app.secureTextFields["password"]
passwordSecureTextField.tap()
passwordSecureTextField.typeText("wrong_password") //here is an error
UI Testing Failure - Aucun élément ni aucun descendant n'a le focus du clavier. Élément:
Qu'est-ce qui ne va pas? Cela fonctionne bien pour textFields
normal, mais le problème ne se pose qu'avec secureTextFields
. Des solutions de contournement?
Ce problème m'a causé beaucoup de souffrance, mais j'ai réussi à trouver une solution appropriée. Dans le simulateur, assurez-vous que «Matériel -> Clavier -> Connecter le clavier matériel» est désactivé.
Récemment, nous avons trouvé un moyen de rendre la solution de la réponse acceptée persistante Pour désactiver les paramètres du simulateur: "Matériel -> Clavier -> Connecter le clavier matériel" à partir de la ligne de commande, vous devez écrire:
defaults write com.Apple.iphonesimulator ConnectHardwareKeyboard 0
Cela n'affectera pas un simulateur en cours d'exécution - vous devez redémarrer le simulateur ou en créer un nouveau pour que ce paramètre ait son effet.
J'ai écrit une petite extension (Swift) qui me convient parfaitement. Voici le code:
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'idée principale est de continuer à appuyer sur un élément (champ de texte) avant que le clavier ne soit présenté.
Stanislav a la bonne idée.
Dans un environnement d'équipe, vous avez besoin de quelque chose qui fonctionnera automatiquement. J'ai trouvé un correctif ici sur mon blog.
Fondamentalement, vous venez de coller:
UIPasteboard.generalPasteboard().string = "Their password"
let passwordSecureTextField = app.secureTextFields["password"]
passwordSecureTextField.pressForDuration(1.1)
app.menuItems["Paste"].tap()
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()
}
Une autre cause de cette erreur est s'il existe une vue parent du champ de texte dans lequel vous essayez de saisir du texte défini comme élément d'accessibilité (view.isAccessibilityElement = true
). Dans ce cas, XCTest n'est pas en mesure d'obtenir un descripteur sur la sous-vue pour saisir le texte et renvoie l'erreur.
UI Testing Failure - Aucun élément, ni aucun descendant n'a de clavier concentrer.
Ce n'est pas qu'aucun élément n'a le focus (comme vous pouvez souvent voir le clavier levé et le curseur clignotant dans UITextField), c'est simplement qu'aucun élément il ne peut atteindre n'a le focus. Je me suis heurté à cela en essayant de saisir du texte dans un UISearchBar. La barre de recherche elle-même n'est pas le champ de texte. Lors de sa définition en tant qu'élément d'accessibilité, l'accès à UITextField sous-jacent était bloqué. Pour résoudre ce problème, searchBar.accessibilityIdentifier = "My Identifier"
a été défini sur UISearchBar
, mais isAccessibilityElement
n'a pas été défini sur true
. Après cela, testez le code de la forme:
app.otherElements["My Identifier"].tap()
app.otherElements["My Identifier"].typeText("sample text")
Travaux
Utilisez un sommeil entre le lancement de l'application et la saisie de données dans des champs de texte comme ceci:
sleep(2)
Dans mon cas, je continuais à avoir cette erreur à chaque fois et seule cette solution m'aidait.
Cela aide peut-être: je viens d'ajouter une action "tap" avant l'erreur; c'est tout :)
[app.textFields[@"theTitle"] tap];
[app.textFields[@"theTitle"] typeText:@"kk"];
[Republier Bartłomiej Semańczyk le commentaire de/comme réponse car cela résout le problème pour moi]
Je devais faire Simulator> Reset Contents and Settings dans la barre de menus du simulateur pour que cela commence à fonctionner pour moi.
Une autre réponse, mais pour nous le problème était que la vue était trop proche d'une autre vue qu'un reconnaissance de geste sur celle-ci. Nous avons constaté que la vue devait être éloignée d’au moins 20 pixels (dans notre cas, ci-dessous). Littéralement 15 ne fonctionnait pas et 20 ou plus le faisaient. C'est étrange, je l'avoue, mais nous avions quelques UITextViews qui fonctionnaient et d'autres qui ne le faisaient pas et qui étaient tous sous le même parent et dont le même positionnement était identique (et les noms de variables bien sûr). Le clavier allumé ou éteint ou quoi que ce soit ne faisait aucune différence. L'accessibilité a montré les champs. Nous avons redémarré nos ordinateurs. Nous avons fait des constructions propres. Checkouts de source fraîche.
Le problème pour moi était le même que pour Ted. En fait, si le champ du mot de passe est exploité après le champ de connexion et que la base de connaissances matérielle est activée, le clavier logiciel s'auto-ignorera lors de la deuxième tape du champ, et ce n'est pas spécifique aux tests d'interface utilisateur.
Après un peu de temps avec AppleScript, voici ce que je propose (les améliorations sont les bienvenues):
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
Créez un fichier de script avec le code ci-dessus et ajoutez-le aux cibles nécessaires (probablement uniquement pour les tests d'interface utilisateur, vous pouvez ajouter un script similaire à vos cibles de développement pour réactiver le clavier matériel pendant le développement) . Vous devez ajouter Run Script
phase in construire des phases et l'utiliser comme ceci: osascript Path/To/Script/script_name.applescript
Parfois, les champs de texte ne sont pas implémentés en tant que champs de texte ou sont encapsulés dans un autre élément d'interface utilisateur et ne sont pas facilement accessibles. Voici un travail autour de:
//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()
Votre première ligne est simplement une définition de query, ce qui ne signifie pas que passwordSecureTextField
existerait réellement.
Votre deuxième ligne va dynamiquement exécuter la requête et essayer de (re) lier la requête à l'élément d'interface utilisateur. Vous devez placer un point d'arrêt dessus et vérifier qu'un seul et même élément est trouvé. Ou utilisez simplement une assertion:
XCTAssertFalse(passwordSecureTextField.exists);
Sinon, cela semble correct, tap
devrait rendre le clavier visible, puis typeText
devrait fonctionner. Le journal des erreurs devrait vous donner plus d’informations.
Nous avons rencontré la même erreur lors de la définition de la valeur accessibilityIdentifier
pour une vue personnalisée (sous-classe UIStackView
) contenant des sous-vues UIControl
. Dans ce cas, XCTest n'a pas pu obtenir le focus clavier pour les éléments descendants.
Notre solution consistait simplement à supprimer la accessibilityIdentifier
de notre vue parent et à définir la accessibilityIdentifier
pour les sous-vues via des propriétés dédiées.
Ce qui a résolu ce problème pour moi, c’est d’ajouter une seconde de sommeil:
let textField = app.textFields["identifier"]
textField.tap()
sleep(1)
textField.typeText(text)
Ne vous trompez pas, le problème est que la raison est que vous avez enregistré votre temps de test. Votre application connectera un clavier matériel alors que votre simulateur de temps de test automatique utilise uniquement un clavier logiciel. donc pour savoir comment résoudre ce problème. Il suffit d’utiliser un clavier logiciel sur votre temps d’enregistrement. vous pouvez voir la magie.