Simone Chelo Simone Chelo - 1 month ago 19
iOS Question

Fill TextField in UI Test Fails

I'm trying to make a simple UI Test in my iOS Application. I'd like to fill a

textfield
with some text but an error always appears.

First try:

let searchField = app.textFields.elementBoundByIndex(0);
searchField.tap()
searchField.typeText("Holy Grail")


The field is highlighted, the keyboard appears and, after some seconds, randomly one of these:

- Timed out waiting for IDE barrier message to complete
- failed to get attributes within 15.0s ui test
- failed to get snaphots within 15.0s ui test


Second try:

func setText(text: String, application: XCUIApplication) {
//Instead of typing the text, it pastes the given text.
UIPasteboard.generalPasteboard().string = text
doubleTap()
application.menuItems["Paste"].tap()
}

...

let searchField = app.textFields.elementBoundByIndex(0);
searchField.tap()
searchField.setText("Holy Grail")


Same result.
Tried with
Connect Hardware Keyboard
on and off.
Tried with iPhone 6s simulator, iPad Retina simulator, iPad 2 simulator.
Tried only with Xcode 7 (8 will break the project)

Ideas? Thanks in advance!

Answer

I don't have an answer on why this is happening, but for any future guy that has my same problem here is my workaround, on which I'm working on.

Basic idea is to make the keyboard appear, and then hit every single key I need to build my string.

func testPlayground() {

    let app = XCUIApplication()
    waitAndTap(app.textFields["MyTextField"])
    type(app, text: "hej")

}

func waitAndTap(elm: XCUIElement){
    let exists = NSPredicate(format: "exists == true")
    expectationForPredicate(exists, evaluatedWithObject: elm, handler: nil)
    waitForExpectationsWithTimeout(10.0, handler: nil)
    elm.tap()
}


func type(app: XCUIApplication, text : String){
    //Wait for the keyboard to appear.
    let k = app.keyboards;
    waitForContent(k, time: 10.0)

    //Capitalize the string.
    var s = text.lowercaseString;
    s.replaceRange(s.startIndex...s.startIndex, with: String(s[s.startIndex]).capitalizedString)

    //For each char I type the corrispondant key.
    var key: XCUIElement;

    for i in s.characters {
        if "0"..."9" ~= i ||  "a"..."z" ~= i || "A"..."Z" ~= i {
            // Then it's alphanumeric!
            key = app.keys[String(i)];
        }
        else {
            // Then is special character and is necessary re-map them.
            switch i {
            case "\n":
                key = app.keys["Next:"]; // This is to generalize A LOT.
            default:
                key = app.keys["space"];
            }

        }

        waitAndTap(key);
    }

So: waitAndTap() is a function that I use A LOT in my tests. It waits for the existence of an element and it taps it. If in ten seconds it doesn't show up, fail the test.

testPlayground() taps the textfield in which I wanna write and then calls type()

type() is the core. Basically, look at every single character in the string and tap it. Problems:

  1. If I look for character H in a keyboard where shift is not activated it will never find an uppercase letter. My solution is to capitalize the string, but it works only in specific cases. This is enhanceable

  2. It doesn't work with special characters, where you cannot look for it exactly, but for the key┬┤s name ("space" instead of " "). Well, no solution here, aside that horrible switch-case, but well, for what I need to do it works.

Hope this can help someone!