swift - para - pruebas de software
Prueba de IU eliminando texto en el campo de texto (12)
En mi prueba tengo un campo de texto con un texto preexistente. Quiero eliminar el contenido y escribir una nueva cadena.
let textField = app.textFields
textField.tap()
// delete "Old value"
textField.typeText("New value")
Al eliminar cadenas con teclado de hardware La grabación no genera nada para mí. Después de hacer lo mismo con el teclado del software, obtuve:
let key = app.keys["Usuń"] // Polish name for the key
key.tap()
key.tap()
... // x times
o
app.keys["Usuń"].pressForDuration(1.5)
Me preocupaba que mi prueba dependiera del idioma, así que he creado algo como esto para mis idiomas compatibles:
extension XCUIElementQuery {
var deleteKey: XCUIElement {
get {
// Polish name for the key
if self["Usuń"].exists {
return self["Usuń"]
} else {
return self["Delete"]
}
}
}
}
Se ve mejor en el código:
app.keys.deleteKey.pressForDuration(1.5)
Pero es muy frágil.
Después de salir del
Toggle software keyboard
Simulator
Toggle software keyboard
se reinició y tengo una prueba fallida.
Mi solución no funciona bien con las pruebas de CI.
¿Cómo se puede resolver esto para ser más universal?
Ahora en
swift 4.2
quizás deberías probar el siguiente código:
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)
}
}
Dado que solucionó su problema de nombre de clave de eliminación localizado en los comentarios de sus preguntas, supongo que puede acceder a la clave de eliminación simplemente llamándolo "Eliminar".
El siguiente código le permitirá eliminar de manera confiable el contenido de su campo:
while (textField.value as! String).characters.count > 0 {
app.keys["Delete"].tap()
}
Pero al mismo tiempo, su problema puede indicar la necesidad de resolver esto de manera más elegante para mejorar la usabilidad de su aplicación.
En el campo de texto también puede agregar un
Clear button
con el que un usuario puede vaciar inmediatamente el campo de texto;
Abra el guión gráfico y seleccione el campo de texto, debajo del inspector de atributos, busque el "botón Borrar" y configúrelo en la opción deseada (por ejemplo, siempre está visible).
Ahora los usuarios pueden borrar el campo con un simple toque en la cruz a la derecha del campo de texto:
O en tu prueba de IU:
textField.buttons["Clear text"].tap()
Encontré la siguiente solución:
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
Cuando toca y mantiene presionado el campo de texto, se abre el menú donde puede tocar el botón "Seleccionar todo". Después de eso, todo lo que necesita es eliminar ese texto con el botón "eliminar" en el teclado o simplemente ingresar texto nuevo. Sobreescribirá el anterior.
Entonces, todavía no encontré ninguna buena solución: /
Y no me gustan las soluciones dependientes de la configuración regional, como la anterior con búsqueda explícita de "Texto claro".
Entonces, escribo check, luego trato de encontrar un botón claro en el campo de texto Funciona bien a menos que tenga un campo de texto personalizado con más de un botón
Mi mejor ahora es (no tengo campos de texto personalizados con más botones):
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
}
Escribí un método de extensión para hacer esto por mí y es bastante rápido:
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)
}
}
Esto se usa con bastante facilidad:
app.textFields["Email"].clearAndEnterText("[email protected]")
Haga esto para eliminar el valor de cadena actual en un cuadro de texto sin depender del teclado virtual.
// lee el valor de tu cuadro de texto en esta variable let textInTextField: String =
let characterCount: Int = textInTextField.count
for _ in 0..<characterCount {
textFields[0].typeText(XCUIKeyboardKey.delete.rawValue)
}
Lo bueno de esta solución es que funciona independientemente de si el simulador tiene teclado virtual o no.
Para aquellos que todavía usan Objective-C
@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
Soy nuevo en las pruebas de IU con iOS, pero pude borrar los campos de texto con esta solución simple. Trabajando con Xcode8 y planea refactorizar esto pronto:
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...
}
Tuve algunas dificultades para que las soluciones anteriores funcionen para un problema similar que tenía: el cursor se colocaría antes del texto y luego trabajaría hacia atrás desde allí. Además, quería verificar que el campo de texto tuviera texto antes de eliminarlo. Aquí está mi solución inspirada en la extensión escribió. Debo señalar que tocar la tecla Eliminar puede llevar mucho tiempo, y puede sustituirse por .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)
}
Usé lo que @oliverfrost describió pero no funcionaba en IPhone XR, lo cambié un poco para mi propio uso, para esto
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) }
}
}
y como dijo @zysoft, puedes usarlo como:
let app = XCUIApplication()
//Just clear text
app.textFields["field1"].clearText()
//Replace text
app.secureTextFields["field2"].clearText(andReplaceWith: "Some Other Text")
esto funcionará para textfield y textview
para 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)
}
}
para SWIFT 4 a 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)
}
}
ACTUALIZAR XCODE 9
Hay un error de manzana en el que si el campo de texto está vacío, el valor y el marcador de posición son iguales
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)
}
}
Xcode 9, Swift 4
Intenté las soluciones anteriores, pero ninguna funcionó debido a un comportamiento extraño en el toque: movió el cursor al comienzo del campo de texto o en algún punto aleatorio del texto. El enfoque que utilicé es lo que @oliverfrost describió here , pero he agregado algunos toques para solucionar los problemas y combinarlos en una extensión ordenada. Espero que pueda ser útil para alguien.
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) }
}
}
Uso:
let app = XCUIApplication()
//Just clear text
app.textFields["field1"].clearText()
//Replace text
app.secureTextFields["field2"].clearText(andReplaceWith: "Some Other Text")