IT Share you

텍스트 필드의 텍스트 삭제 UI 테스트

shareyou 2020. 12. 2. 22:12
반응형

텍스트 필드의 텍스트 삭제 UI 테스트


내 테스트에는 기존 텍스트가있는 텍스트 필드가 있습니다. 콘텐츠를 삭제하고 새 문자열을 입력하고 싶습니다.

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 테스트에서 잘 작동하지 않습니다. 이 문제를 어떻게 해결할 수 있습니까?


이 작업을 수행하기 위해 확장 메서드를 작성했으며 매우 빠릅니다.

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("newemail@domain.com")


질문 댓글에서 현지화 된 삭제 키 이름 문제를 해결 했으므로 "Delete"라고 부르기 만하면 삭제 키에 액세스 할 수 있다고 가정합니다.

아래 코드를 사용하면 필드의 내용을 안정적으로 삭제할 수 있습니다.

    while (textField.value as! String).characters.count > 0 {
        app.keys["Delete"].tap()
    }

그러나 동시에 문제는 앱의 유용성을 개선하기 위해이 문제를보다 우아하게 해결해야한다는 것을 나타낼 수 있습니다. 텍스트 필드 Clear button에서 사용자가 텍스트 필드를 즉시 비울 수있는를 추가 할 수도 있습니다 .

스토리 보드를 열고 텍스트 필드를 선택하고 속성 관리자에서 "Clear button"을 찾아 원하는 옵션으로 설정합니다 (예 : 항상 표시됨).

버튼 선택 지우기

이제 사용자는 텍스트 필드 오른쪽의 십자 표시를 간단히 탭하여 필드를 지울 수 있습니다.

지우기 버튼

또는 UI 테스트에서 :

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)
    }
}

위한 SWIFT 4SWIFT 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 업데이트

사과 버그 텍스트 필드가 비어있는 경우, 값과 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)
    }
}

그래서 아직 좋은 해결책을 찾지 못했습니다 : /

그리고 위와 같이 명시적인 "일반 텍스트"조회를 사용하는 로케일 종속 솔루션을 좋아하지 않습니다.

그래서 입력 확인을 한 다음 텍스트 필드에서 지우기 버튼을 찾으려고 노력합니다. 하나 이상의 버튼이있는 사용자 정의 텍스트 필드가 없으면 잘 작동합니다.

지금 내 최고는 (더 많은 버튼이있는 사용자 정의 텍스트 필드가 없습니다) :

    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")

아직 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

I had some difficulty getting the above solutions to work for a similar problem I was having: The curser would place itself before text and then work backwards from there. Additionally, I wanted to check that the textfield had text in it before deleting. Here's my solution inspired by the extension https://stackoverflow.com/users/482361/bay-phillips wrote. I should note that the tapping the delete key can take a long time, and it can be substituted with .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)
    }

I am new to UI testing with iOS but I was able to clear text fields with this simple workaround. Working with Xcode8 and plan on refactoring this soon:

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...
}

Do this to delete the current string value in a text box without relying on virtual keyboard.

//read the value of your text box in this variable let textInTextField:String =

  let characterCount: Int = textInTextField.count
  for _ in 0..<characterCount {
    textFields[0].typeText(XCUIKeyboardKey.delete.rawValue)
  }

이 솔루션의 좋은 점은 시뮬레이터에 가상 키보드가 있는지 여부에 관계없이 작동한다는 것입니다.


이제 swift 4.2아마도 다음 코드를 시도해야합니다.

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)
    }
}

@oliverfrost가 설명한 것을 사용했지만 IPhone XR에서 작동하지 않았으며 내 사용을 위해 약간 변경했습니다.

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) }
}
}

@zysoft가 말했듯이 다음과 같이 사용할 수 있습니다.

let app = XCUIApplication()
//Just clear text
app.textFields["field1"].clearText() 
//Replace text    
app.secureTextFields["field2"].clearText(andReplaceWith: "Some Other Text")

참고 URL : https://stackoverflow.com/questions/32821880/ui-test-deleting-text-in-text-field

반응형