Reputation: 1724
I am trying to build a function findElementWithLabel() that can recursively walk the entire XCUIElement tree for any given element and return a child element with a specified label or id. Unlike the built in childrenMatchingType() function it will search children more than one level deep (not just direct children). I have built this function as an extension on XCUIElement, here is the sample code:
public extension XCUIElement {
public func findElementWithLabel(label: String) -> XCUIElement? {
return findElementWithName(self, name:label)
}
private func findElementWithName(elementToSearch:XCUIElement?, name: String) -> XCUIElement? {
if let currentElement = elementToSearch {
if currentElement.label == name {
return currentElement
}
} else {
return nil
}
let children = elementToSearch?.childrenMatchingType(.Any)
var loopIndex:UInt = 0
while (loopIndex < children?.count) {
let foundElement = findElementWithName(children?.elementBoundByIndex(loopIndex), name:name)
if let unwrappedFoundElement = foundElement {
return unwrappedFoundElement
}
loopIndex += 1
}
return nil
}
}
The function returns the proper result, but unfortunately the performance is horrible taking almost 10-15 seconds to return. Can any experts on xcode ui automation help me deduce what could be causing this? Originally I thought it was the repeated calls to "XCUIElement.childrenMatchingType(.Any)" however I think I can rule this out. The function on average takes 0.007 seconds to compute, and I invoke it roughly 30 times which means that can't be the culprit. The only other theories I have are:
1) Some delays are being applied somewhere, greatly affecting the run-time. I wrote this function in instruments with the javascript api and invoking UIATarget.localTarget().pushTimeout(0) before the tree traversal with a popTimeout(0) after did the trick. This essentially caused my recursive function calls to not delay and wait on any elements... If this is the culprit is there some way I can achieve this global pushTimeout() and popTimeout() functionality with the new API?
2) The huge amounts of xcode console logging with the new ui-automation must be affecting runtime. I know NSLog's are synchronous and slow, so could this be the culprit? If so how can we switch these logs off? How can this even scale going forward, if the built in xcode xctest debug logs affect run-time so immensely. As devs we need these logs, but we also can not have it affect runtime like this.
Upvotes: 3
Views: 948
Reputation: 1724
I found out the answer to my question. It seems my recursive call was working at the Element level and I should be working at the ElementQuery level. Writing a query runs much faster because the element gets resolved once and only once, then resolves the query chain.
It seems in the new API resolving an element is very costly as it communicates with the app to resolve and verify the element every single time. I suspect the Javascript API was doing this as well, but since they did not expose any ElementQuery structure they allowed you to push a timeout of 0, telling the framework to not delay and wait to resolve each element. Anyway, the answer to my question was just use descendantsOfElement() on the root element and write a label/id query.
Upvotes: 1