Thermometer Thermometer - 29 days ago 8
iOS Question

How to UITest UIProgressView?

Situation:

I want to UI-test my progress view and see if it's progress has increased.

What I've tried:

By using a breakpoint in my UI-test and using the

po print(app.debugDescription
), I can successfully see and access the
UIProgressView
element.

It's called:
Other, 0x6080003869a0, traits: 8589935104, {{16.0, 285.5}, {343.0, 32.0}}, identifier: 'progressView', label: 'Progress', value: 5%


I access it with
let progressView = secondTableViewCell.otherElements["progressView"]
, which works, as
.exists
returns true.

Now, to check progress, the description above hints at the 'value' property, that is currently at 5%. However, when I try
progressView.value as! String
or Double or whichever, I cannot seem to get the property as it isn't NSCoder-compliant.

Question:

Is it possible to UI-test a UIProgressView and use it's progress value?

My final custom solution:

Using the value property (when casting to String) somehow does work now. As I wanted to check if progress increased over time, I strip the String to get the numeric progress in it to compare. Here is my solution I use now:

// Check if progress view increases over time
let progressView = secondTableViewCell.otherElements["progressView"]
XCTAssert(progressView.exists)

let progressViewValueString = progressView.value as! String
// Extract numeric value from '5%' string
let progressViewValue = progressViewValueString.components(separatedBy: CharacterSet.decimalDigits.inverted).joined()

// Let progress increase
sleep(3)

let newProgressViewValueString = progressView.value as! String
let newProgressViewValue = newProgressViewValueString.components(separatedBy: CharacterSet.decimalDigits.inverted).joined()
XCTAssert(newProgressViewValue > progressViewValue)

Answer Source

XCUIElement conforms to XCUIElementAttributes which gives you access to a value property of type Any?

The actual type of value at runtime depends on which kind of UI element you are querying. In case of a UIProgressView it is of type __NSCFString, which is a concrete subclass of NSString. Which means you can safely cast it to String:

This works (provided that you set your progress view's accessibility identifier to "progressView"):

func testProgressView() {
   let app = XCUIApplication()
   app.launch()

   let progressView = app.progressIndicators["progressView"]
   // alternative (if the above query does not work):
   // let progressView = app.otherElements["progressView"]
   let currentValue = progressView.value as? String
   XCTAssertEqual(currentValue, "5 %")
}

Weirdly in some cases the progressIndicator query does not work. In that case you can try a otherElements query (see comment in above code)