'How do I assert that a text field is empty?

I have an empty text field on my UI, though it has a placeholder text (whose value is foo) set in the storyboard. In my UI test, I am trying to check that its text value starts out empty, but when I query it's value, it seems to be giving me the placeholder value instead:

func testTextFieldInitiallyEmpty {
  let input = XCUIApplication().textFields["My Text Field"]
  XCTAssertEqual(input.value as! String, "")
}

as the test fails with this message:

XCTAssertEqual failed: ("foo") is not equal to ("")

Of course, foo is the placeholder value, but it's not the text value of that text field. I would have expected that error message if I had written:

XCTAssertEqual(input.placeholderValue as! String, "")

input is a XCUIElement, which implements XCUIElementAttributes, so I don't see anything else that would do the trick here.

How do I check (assert) that the text field is empty?

storyboardattributes inspector

Edit

After doing some further research and trying out the suggestions below for using the input's properties of accessibilityValue, label, and title, I have not found any solution that will give me the text field's text value when there is text, and an empty string when only the placeholder is visible.

This seems like either (a) a bug, or (b) a questionable design decision from the test framework to not provide that ability. At a minimum, the documentation for XCUIElementAttributes#value seems inadequate to me, as the only detail is:

The exact type of value varies based on the type of the element.

Still looking for a better solution...



Solution 1:[1]

You can compare to the XCUIElementAttributes's placeholderValue variable in addition to checking for a blank string

extension XCUIElement {
    func noTextEntered() -> Bool {
        return self.value as? String != "" && self.value as? String != placeholderValue
    }
}

Then you can run XCAssert(input.noTextEntered(), "Unexpected text entered into field")

Just make sure your placeholder is not something a user would type in. This way you don't have to hardcode placeholder values to check against

Solution 2:[2]

Kind of ridiculous that this is actually the case it works and that it needs a workaround. Anyway, my solution to get the value w/o the placeholder interfering, based on @Jason's answer.

extension XCUIElement {
    var valueWithoutPlaceholder: String {
        if let v = value as? String, v != placeholderValue {
            return v
        }
        return ""
    }
}

Be aware, if the input is actually the placeholder this would break!

Solution 3:[3]

Try using accessibilityValue property of input.

func testTextFieldInitiallyEmpty {
  let input = XCUIApplication().textFields["My Text Field"]
  XCTAssertEqual(input.accessibilityValue, "")
}

If you command+click the property, you can see the following..

    /*
     Returns a localized string that represents the value of the element, such as the value 
     of a slider or the text in a text field. Use only when the label of the element
     differs from a value. For example: A volume slider has a label of "Volume", but a value of "60%".
     default == nil
     default on UIKit controls == values for appropriate controls 
     Setting the property will change the value that is returned to the accessibility client.  
     */
    public var accessibilityValue: String?

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Jason
Solution 2 Deitsch
Solution 3