Home > database >  XCUIElementQuery in SwiftUI testing returns inconsistent count
XCUIElementQuery in SwiftUI testing returns inconsistent count

Time:08-24

I'm doing UI testing of a SwiftUI view, and I have the following code to fetch a List element to check the count of staticTexts in it:

let pred = NSPredicate(format: "identifier == 'detailViewTable'")
let detailViewTable = app.descendants(matching: .any).matching(pred).firstMatch
let arrOfTexts = detailViewTable.staticTexts
let ct = arrOfTexts.count
print("Count is: \(ct)") // This prints 0
print("Count is now: \(detailViewTable.staticTexts.count)") // Also prints 0

The count always prints as 0.

The SwiftUI view basically looks like this:

List {
   Section(header: Text("Item list")) {
     HStack {
        Text("Number")
        Spacer()
        Text(rec.recNum)
     }
   }
// Lots more Sections/HStacks/Texts/etc here 
// ...
// ...
}
.accessibility(identifier: "detailViewTable")
.listStyle(.grouped)

When I put a breakpoint as shown,

enter image description here

and use po in the Debug Console, I get 0 for ct, but 21 if calling count directly:

(lldb) po ct
0
(lldb) po detailViewTable.staticTexts.count
21

Pic here:

enter image description here

Why is the var ct set to 0, but calling the count directly gives me the correct number 21?

It makes me wonder if the XCUIElementQuery takes a moment to run and returns the answer in some kind of implicit callback, and the data isn't ready at the moment the variable ct is set, but will return the correct answer in the debug console because it waits for the response. However, I don't see any discussion of a callback in the Apple documentation:

https://developer.apple.com/documentation/xctest/xcuielementquery

CodePudding user response:

This answer

https://stackoverflow.com/a/37320452

pointed me in the right direction. The fix is to put a pause in the form of sleep(1), to give the query time to do its fetch, I assume.

let pred = NSPredicate(format: "identifier == 'detailViewTable'")
let detailViewTable = app.descendants(matching: .any).matching(pred).firstMatch
let arrOfTexts = detailViewTable.staticTexts
sleep(1) // <-- Add this
let ct = arrOfTexts.count
print("Count is: \(ct)") // Now prints 21
print("Count is now: \(detailViewTable.staticTexts.count)") // Also prints 21
  • Related