In meinem Test habe ich ein Textfeld mit einem bereits vorhandenen Text. Ich möchte den Inhalt löschen und eine neue Zeichenfolge eingeben.
let textField = app.textFields
textField.tap()
// delete "Old value"
textField.typeText("New value")
Beim Löschen von Zeichenfolgen mit Hardwaretastatur wird für mich keine Aufzeichnung generiert. Nachdem ich dasselbe mit der Software-Tastatur gemacht hatte, bekam ich:
let key = app.keys["Usuń"] // Polish name for the key
key.tap()
key.tap()
... // x times
oder
app.keys["Usuń"].pressForDuration(1.5)
Ich habe mir Sorgen gemacht, dass mein Test sprachabhängig ist, deshalb habe ich für meine unterstützten Sprachen Folgendes erstellt:
extension XCUIElementQuery {
var deleteKey: XCUIElement {
get {
// Polish name for the key
if self["Usuń"].exists {
return self["Usuń"]
} else {
return self["Delete"]
}
}
}
}
Im Code sieht es besser aus:
app.keys.deleteKey.pressForDuration(1.5)
aber es ist sehr zerbrechlich. Nach dem Beenden von Simulator Toggle software keyboard
wurde zurückgesetzt und ich habe einen fehlgeschlagenen Test. Meine Lösung funktioniert nicht gut mit CI-Tests. Wie kann dies gelöst werden, um universeller zu sein?
swift
uitextfield
xcode7
uikeyboard
xcode-ui-testing
Tomasz Bąk
quelle
quelle
Toggle software keyboard
Einstellung zu haben. Gibt es noch etwas in der Textansicht, das die Tastatur verbergen / schließen könnte?Toggle software keyboard
zurückgesetzt. Es ist nicht die Standardeinstellung für den Simulator (und ich weiß nicht, ob dies geändert werden kann). Auf die eine oder andere Weise ist meine Methode erst dann zuverlässig, wenn Sie die Sprach- und Softwaretastatureinstellungen auf der Ebene des Tests (oder des Testschemas) korrigieren können.Antworten:
Ich habe eine Erweiterungsmethode geschrieben, um dies für mich zu tun, und sie ist ziemlich schnell:
extension XCUIElement { /** Removes any current text in the field before typing in the new value - Parameter text: the text to enter into the field */ func clearAndEnterText(text: String) { guard let stringValue = self.value as? String else { XCTFail("Tried to clear and enter text into a non string value") return } self.tap() let deleteString = String(repeating: XCUIKeyboardKey.delete.rawValue, count: stringValue.count) self.typeText(deleteString) self.typeText(text) } }
Dies ist dann ziemlich einfach zu verwenden:
app.textFields["Email"].clearAndEnterText("[email protected]")
quelle
let deleteString = stringValue.characters.map { _ in "\u{8}" }.joinWithSeparator("")
joinWithSeparator
in Swift 2 hinzugefügt hatten . Danke!let deleteString = String(repeating: XCUIKeyboardKey.delete.rawValue, count: stringValue.characters.count)
let deleteString = String(repeating: XCUIKeyboardKey.delete.rawValue, count: stringValue.count)
Da Sie Ihr lokalisiertes Problem mit dem Namen des Löschschlüssels in den Kommentaren Ihrer Fragen behoben haben, gehe ich davon aus, dass Sie auf den Löschschlüssel zugreifen können, indem Sie ihn einfach "Löschen" nennen.
Mit dem folgenden Code können Sie den Inhalt Ihres Feldes zuverlässig löschen:
while (textField.value as! String).characters.count > 0 { app.keys["Delete"].tap() }
oder Swift 4+:
while !(textView.value as! String).isEmpty { app.keys["Delete"].tap() }
Gleichzeitig weist Ihr Problem möglicherweise darauf hin, dass dies eleganter gelöst werden muss, um die Benutzerfreundlichkeit Ihrer App zu verbessern. Im Textfeld können Sie auch ein hinzufügen,
Clear button
mit dem ein Benutzer das Textfeld sofort leeren kann.Öffnen Sie das Storyboard und wählen Sie das Textfeld aus. Suchen Sie unter dem Attributinspektor die Schaltfläche "Löschen" und stellen Sie die gewünschte Option ein (z. B. ist immer sichtbar).
Jetzt können Benutzer das Feld durch einfaches Tippen auf das Kreuz rechts neben dem Textfeld löschen:
Oder in Ihrem UI-Test:
textField.buttons["Clear text"].tap()
quelle
Dies funktioniert für Textfeld und Textansicht
für SWIFT 3
extension XCUIElement { func clearText() { guard let stringValue = self.value as? String else { return } var deleteString = String() for _ in stringValue { deleteString += XCUIKeyboardKeyDelete } self.typeText(deleteString) } }
für SWIFT 4 , SWIFT 5
extension XCUIElement { func clearText() { guard let stringValue = self.value as? String else { return } var deleteString = String() for _ in stringValue { deleteString += XCUIKeyboardKey.delete.rawValue } typeText(deleteString) } }
UPDATE XCODE 9
Es gibt einen Apple-Fehler, bei dem Wert und Platzhalterwert gleich sind, wenn das Textfeld leer ist
extension XCUIElement { func clearText() { guard let stringValue = self.value as? String else { return } // workaround for apple bug if let placeholderString = self.placeholderValue, placeholderString == stringValue { return } var deleteString = String() for _ in stringValue { deleteString += XCUIKeyboardKey.delete.rawValue } typeText(deleteString) } }
quelle
Ich habe folgende Lösung gefunden:
let myTextView = app.textViews["some_selector"] myTextView.pressForDuration(1.2) app.menuItems["Select All"].tap() app.typeText("New text you want to enter") // or use app.keys["delete"].tap() if you have keyboard enabled
Wenn Sie auf das Textfeld tippen und es gedrückt halten, wird ein Menü geöffnet, in dem Sie auf die Schaltfläche "Alle auswählen" tippen können. Danach müssen Sie nur noch diesen Text mit der Schaltfläche "Löschen" auf der Tastatur entfernen oder einfach neuen Text eingeben. Es wird das alte überschreiben.
quelle
myTextView.doubleTap()
, um das MenüXcode 9, Swift 4
Versuchte die obigen Lösungen, aber keine funktionierte aufgrund eines seltsamen Verhaltens beim Tippen - es bewegte den Cursor entweder zum Anfang des Textfelds oder an einem zufälligen Punkt im Text. Der Ansatz, den ich verwendet habe, ist der von @oliverfrost hier beschriebene , aber ich habe einige Details hinzugefügt, um die Probleme zu umgehen und sie in einer ordentlichen Erweiterung zu kombinieren. Ich hoffe, es kann für jemanden nützlich sein.
extension XCUIElement { func clearText(andReplaceWith newText:String? = nil) { tap() tap() //When there is some text, its parts can be selected on the first tap, the second tap clears the selection press(forDuration: 1.0) let selectAll = XCUIApplication().menuItems["Select All"] //For empty fields there will be no "Select All", so we need to check if selectAll.waitForExistence(timeout: 0.5), selectAll.exists { selectAll.tap() typeText(String(XCUIKeyboardKey.delete.rawValue)) } if let newVal = newText { typeText(newVal) } } }
Verwendung:
let app = XCUIApplication() //Just clear text app.textFields["field1"].clearText() //Replace text app.secureTextFields["field2"].clearText(andReplaceWith: "Some Other Text")
quelle
Also habe ich noch keine gute Lösung gefunden: /
Und ich mag keine länderabhängigen Lösungen wie oben mit expliziter "Klartext" -Suche.
Also mache ich eine Typprüfung und versuche dann, eine klare Schaltfläche im Textfeld zu finden. Es funktioniert gut, es sei denn, Sie haben ein benutzerdefiniertes Textfeld mit mehr als einer Schaltfläche
Mein Bestes ist jetzt (ich habe keine benutzerdefinierten Textfelder mit mehr Schaltflächen):
class func clearTextField(textField : XCUIElement!) -> Bool { guard textField.elementType != .TextField else { return false } let TextFieldClearButton = textField.buttons.elementBoundByIndex(0) guard TextFieldClearButton.exists else { return false } TextFieldClearButton.tap() return true }
quelle
Ich habe eine Lösung gefunden, die eine iOS-Funktion verwendet, mit der die gesamten Textfelder durch mehrmaliges Tippen ausgewählt werden. Anschließend löschen wir das Textfeld durch Eingabe eines beliebigen Zeichens oder durch Drücken von Löschen (wenn die Tastatur aktiviert ist).
let myTextView = app.textViews["some_selector"] myTextView.tap(withNumberOfTaps: 2, numberOfTouches: 1) app.typeText("New text you want to enter") // or use app.keys["delete"].tap() if you have keyboard enabled
quelle
let toSelectWord = 2 // Select a word: Double-tap the word with one finger.
let toSelectSentence = 3 // Select a sentence: Triple-tap the sentence with one finger.
let toSelectParagraph = 4 // Select a paragraph: Quadruple-tap with one finger.
app.textFields["sd.Title"].tap()
app.textFields["sd.Title"].tap(withNumberOfTaps: toSelectParagraph, numberOfTouches: 1)
app.textFields["sd.Title"].typeText("Old Task")
withNumberOfTaps: 2
ist ausreichend.Führen Sie dies aus, um den aktuellen Zeichenfolgenwert in einem Textfeld zu löschen, ohne auf die virtuelle Tastatur angewiesen zu sein.
// Lies den Wert deines Textfeldes in dieser Variablen let textInTextField: String =
let characterCount: Int = textInTextField.count for _ in 0..<characterCount { textFields[0].typeText(XCUIKeyboardKey.delete.rawValue) }
Das Gute an dieser Lösung ist, dass sie unabhängig davon funktioniert, ob der Simulator über eine virtuelle Tastatur verfügt oder nicht.
quelle
swift 4.2
Vielleicht sollten Sie jetzt den folgenden Code ausprobieren:extension XCUIElement { /** Removes any current text in the field before typing in the new value - Parameter text: the text to enter into the field */ func clearAndEnterText(text: String) { guard let stringValue = self.value as? String else { XCTFail("Tried to clear and enter text into a non string value") return } self.tap() for _ in 0..<stringValue.count { self.typeText(XCUIKeyboardKey.delete.rawValue) } self.typeText(text) } }
quelle
Für diejenigen, die noch Objective-C verwenden
@implementation XCUIElement (Extensions) -(void)clearText{ if (!self){ return; } if (![self.value isKindOfClass:[NSString class]]){ return; } NSString* stringValue = (NSString*)self.value; for (int i=0; i<stringValue.length ; i++) { [self typeText:XCUIKeyboardKeyDelete]; } } @end
quelle
Ich hatte einige Schwierigkeiten, die oben genannten Lösungen für ein ähnliches Problem zum Laufen zu bringen: Der Cursor stellte sich vor den Text und arbeitete dann von dort aus rückwärts. Außerdem wollte ich vor dem Löschen überprüfen, ob das Textfeld Text enthält. Hier ist meine Lösung, inspiriert von der Erweiterung, die https://stackoverflow.com/users/482361/bay-phillips geschrieben hat. Ich sollte beachten, dass das Tippen auf die Löschtaste lange dauern kann und durch .pressForDuration ersetzt werden kann
func clearAndEnterText(element: XCUIElement, text: String) -> Void { guard let stringValue = element.value as? String else { XCTFail("Tried to clear and enter text into a non string value") return } element.tap() guard stringValue.characters.count > 0 else { app.typeText(text) return } for _ in stringValue.characters { app.keys["delete"].tap() } app.typeText(text) }
quelle
Ich bin neu im Testen von Benutzeroberflächen mit iOS, konnte jedoch Textfelder mit dieser einfachen Problemumgehung löschen. Arbeiten Sie mit Xcode8 und planen Sie, dies bald zu überarbeiten:
func testLoginWithCorrectUsernamePassword() { //Usually this will be completed by Xcode let app = XCUIApplication() //Set the text field as a constant let usernameTextField = app.textFields["User name"] //Set the delete key to a constant let deleteKey = app.keys["delete"] //Tap the username text field to toggle the keyboard usernameTextField.tap() //Set the time to clear the field. generally 4 seconds works deleteKey.press(forDuration: 4.0); //Enter your code below... }
quelle
Ich habe das verwendet, was @oliverfrost beschrieben hat, aber es funktionierte nicht auf IPhone XR. Ich habe es ein wenig für meinen eigenen Gebrauch geändert
extension XCUIElement { func clearText(andReplaceWith newText:String? = nil) { tap() tap() //When there is some text, its parts can be selected on the first tap, the second tap clears the selection press(forDuration: 1.0) let select = XCUIApplication().menuItems["Select"] //For empty fields there will be no "Select All", so we need to check if select.waitForExistence(timeout: 0.5), select.exists { select.tap() typeText(String(XCUIKeyboardKey.delete.rawValue)) } if let newVal = newText { typeText(newVal) } } }
und wie @zysoft sagte, können Sie es wie folgt verwenden:
let app = XCUIApplication() //Just clear text app.textFields["field1"].clearText() //Replace text app.secureTextFields["field2"].clearText(andReplaceWith: "Some Other Text")
quelle
Swift 5
basierend auf @ Bay Phillips Antwort,
extension XCUIElement { func clearAndEnterText(text: String) { guard let stringValue = self.value as? String else { XCTFail("Tried to clear and enter text into a non string value") return } self.tap() let deleteString = stringValue.map { _ in "\u{8}" }.joined(separator: "") self.typeText(deleteString) self.typeText(text) } }
quelle