Тест пользовательского интерфейса удаление текста в текстовом поле
В моем тесте у меня есть текстовое поле с уже существующим текстом. Я хочу удалить содержимое и ввести новую строку.
let textField = app.textFields
textField.tap()
// delete "Old value"
textField.typeText("New value")
При удалении строки с аппаратной клавиатуры запись сгенерировала для меня ничего. Проделав то же самое с программной клавиатурой, я получил:
let key = app.keys["Usuń"] // Polish name for the key
key.tap()
key.tap()
... // x times
Или
app.keys["Usuń"].pressForDuration(1.5)
Я беспокоился, что мой тест зависит от языка, поэтому я создал что-то вроде этого для моих поддерживаемых языков:
extension XCUIElementQuery {
var deleteKey: XCUIElement {
get {
// Polish name for the key
if self["Usuń"].exists {
return self["Usuń"]
} else {
return self["Delete"]
}
}
}
}
Он выглядит лучше в коде:
app.keys.deleteKey.pressForDuration(1.5)
Но это очень хрупкий. После выхода из симулятора Toggle software keyboard был сброшен, и я получил неудачный тест. Мое решение плохо работает с тестированием CI. Как это можно решить, чтобы быть более универсальным?
9 ответов:
Я написал метод расширения, чтобы сделать это для меня, и это довольно быстро:
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 = stringValue.characters.map { _ in XCUIKeyboardKeyDelete }.joined(separator: "") self.typeText(deleteString) self.typeText(text) } }Это затем используется довольно легко:
app.textFields["Email"].clearAndEnterText("[email protected]")
Поскольку вы исправили локализованную проблему с именем ключа удаления в комментариях к вашим вопросам, я предполагаю, что вы можете получить доступ к ключу удаления, просто назвав его "удалить".
Приведенный ниже код позволит вам надежно удалить содержимое вашего поля:
while (textField.value as! String).characters.count > 0 { app.keys["Delete"].tap() }Но в то же время, ваша проблема может указывать на необходимость решить эту проблему более элегантно, чтобы улучшить удобство использования вашего приложения. В текстовом поле можно также добавить
Clear button, с помощью которого пользователь может немедленно очистить текст области;Откройте раскадровку и выделите текстовое поле, под инспектором атрибутов найдите "кнопку Очистить" и установите ее в нужную опцию (например, всегда видна).
Теперь пользователи могут очистить поле простым нажатием на крестик справа от текстового поля:Или в тесте пользовательского интерфейса:
textField.buttons["Clear text"].tap()
Я нашел следующее решение:
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Когда вы нажимаете и удерживаете текстовое поле, открывается меню, в котором вы можете нажать на кнопку "Выбрать все". После этого все, что вам нужно, это удалить этот текст с помощью кнопки "Удалить" на клавиатуре или просто ввести новый текст. Он перепишет старый.
Это будет работать для textfield и textview
Для 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) } }For SWIFT 4 to SWIFT 99
extension XCUIElement { func clearText() { guard let stringValue = self.value as? String else { return } var deleteString = String() for _ in stringValue { deleteString += XCUIKeyboardKey.delete.rawValue } self.typeText(deleteString) } }ОБНОВИТЬ XCODE 9
Существует ошибка apple, где если текстовое поле пусто, значение и placeholderValue равны
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 } self.typeText(deleteString) } }
Итак, я пока не нашел никакого хорошего решения : /
И мне не нравятся решения, зависящие от локали, как выше, с явным поиском "открытого текста".
Итак, я набираю check, затем пытаюсь найти кнопку clear в текстовом поле Это хорошо работает, если у вас нет пользовательского текстового поля с более чем одной кнопкой
Мой лучший сейчас (у меня нет пользовательских текстовых полей с большим количеством кнопок):
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 }
Xcode 9, Swift 4
Пробовал решения выше, но ни одно из них не сработало из - за какого-то странного поведения при нажатии-он перемещал курсор либо в начало текстового поля, либо в какую-то случайную точку текста. Подход, который я использовал, описан @oliverfrost здесь , но я добавил некоторые штрихи, чтобы обойти проблемы и объединить их в аккуратное расширение. Я надеюсь, что это может быть полезно для кого-то.
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) } } }Использование:
let app = XCUIApplication() //Just clear text app.textFields["field1"].clearText() //Replace text app.secureTextFields["field2"].clearText(andReplaceWith: "Some Other Text")
У меня были некоторые трудности с тем, чтобы вышеприведенные решения работали для аналогичной проблемы, которая у меня была: curser помещал себя перед текстом, а затем работал в обратном направлении. Кроме того, я хотел проверить, что текстовое поле содержит текст перед удалением. Вот мое решение, вдохновленное расширением https://stackoverflow.com/users/482361/bay-phillips написал. Я должен отметить, что нажатие клавиши delete может занять много времени, и ее можно заменить на .pressForDuration
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) }
Я новичок в тестировании пользовательского интерфейса с iOS, но мне удалось очистить текстовые поля с помощью этого простого обходного пути. Работа с Xcode8 и план по рефакторингу в ближайшее время:
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... }
Сделайте это, чтобы удалить текущее строковое значение в текстовом поле, не полагаясь на виртуальную клавиатуру.
/ / считайте значение вашего текстового поля в этой переменной пусть textInTextField: String =
let characterCount: Int = textInTextField.count for _ in 0..<characterCount { textFields[0].typeText(XCUIKeyboardKey.delete.rawValue) }Хорошая вещь в этом решении заключается в том, что оно работает независимо от того, есть у симулятора виртуальная клавиатура или нет.


Comments