如何递归搜索具有良好性能的XCUIElement树?

时间:2016-08-19 05:48:57

标签: ios swift xcode testing xcode-ui-testing

我正在尝试构建一个函数findElementWithLabel(),它可以递归遍历任何给定元素的整个XCUIElement树,并返回具有指定标签或id的子元素。与内置的childrenMatchingType()函数不同,它将搜索多个级别的子级(不仅仅是直接子级)。我已经将此函数构建为XCUIElement的扩展,下面是示例代码:

    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
        }

    }

该函数返回正确的结果,但不幸的是,性能很糟糕需要大约10-15秒才能返回。任何有关xcode ui自动化的专家都可以帮助我推断出可能导致这种情况的原因吗?最初我以为是重复调用&#34; XCUIElement.childrenMatchingType(.Any)&#34;但我认为我可以排除这种情况。该函数平均需要0.007秒来计算,我调用它大约30次,这意味着它不能成为罪魁祸首。我唯一的其他理论是:

1)某些地方正在应用某些延迟,这极大地影响了运行时间。我在使用javascript api的工具中编写了这个函数,并在使用popTimeout(0)进行树遍历之后调用了UIATarget.localTarget()。pushTimeout(0)。这实际上导致我的递归函数调用没有延迟并等待任何元素......如果这是罪魁祸首,我可以通过某种方式使用新API实现这个全局pushTimeout()和popTimeout()功能吗?

2)使用新的ui-automation进行大量的xcode控制台日志记录必须影响运行时。我知道NSLog是同步和慢的,所以这可能是罪魁祸首吗?如果是这样,我们如何关闭这些日志?如果内置的xcode xctest调试日志如此极大地影响运行时,那么如何进行均衡扩展呢?作为开发人员,我们需要这些日志,但我们也不能像这样影响运行时。

1 个答案:

答案 0 :(得分:1)

我找到了问题的答案。看来我的递归调用是在Element级别工作,我应该在ElementQuery级别工作。编写查询的速度要快得多,因为元素只解析一次,然后解析查询链。

似乎在新的API中解析元素是非常昂贵的,因为它与应用程序通信以每次解析和验证元素。我怀疑Javascript API也是这样做的,但由于它们没有暴露任何ElementQuery结构,因此它们允许你将超时推送到0,告诉框架不要延迟并等待解决每个元素。无论如何,我的问题的答案只是在根元素上使用descendantsOfElement()并编写标签/ id查询。