0

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)
Thermometer
  • 2,567
  • 3
  • 20
  • 41
  • 1
    `let progressView = app.otherElements["progress"]` didn't work for me. But this did: let x = app.progressIndicators["progress"] XCTAssertTrue(x.exists) XCTAssertEqual(x.value as! String, "55%") – Michał Myśliwiec Sep 21 '17 at 16:30
  • Weird, I'm getting the opposite with iOS 11 simulator and XCode 9. Exists works for the `otherElements` property, but not for the `progressIndicators` property :/. Thanks for the suggestion though! – Thermometer Sep 22 '17 at 12:34

1 Answers1

3

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)

joern
  • 27,354
  • 7
  • 90
  • 105
  • I don't know why, but somehow casting to String didn't work before and now it does. However, `progressIndicators` doesn't work for me to get a `UIProgressView` element. `otherElements` does for me. If you change it to that, I'll accept the answer – Thermometer Sep 22 '17 at 12:35
  • That's weird. In my case (Xcode9, iPhone8 Simulator) it's the other way around: `otherElements` does not work, `progressIndicators` does work. I'll add both queries to the answer. – joern Sep 22 '17 at 13:23
  • Thanks. Weird indeed, as many UITesting things are at the moment :(. – Thermometer Sep 22 '17 at 13:31