【问题标题】:Is there a way to clear/refresh the accessibility hierarchy cache有没有办法清除/刷新可访问性层次缓存
【发布时间】:2016-03-23 02:07:36
【问题描述】:

我有一个 UI 测试检查静态文本元素的值,等待几秒钟并再次检查以确认更改。起初它不起作用,因为层次结构没有更新。我在日志中注意到了这一点;

使用缓存的可访问性层次结构

我已经为此提供了一种解决方法,只需向菜单添加一个点击并打开/关闭它,以便合成事件并更新层次结构。

但是,如果有办法直接清除缓存或强制更新,那就更好了。我还没有在 API 中找到一个。我错过了什么吗?

有什么想法吗?

这就是我正在做的;

XCTAssertEqual(app.staticTexts["myText"].label, "Expected 1")
sleep(20)
menu.tap()
sleep(1)
menu.tap()
XCTAssertEqual(app.staticTexts["myText"].label, "Expected 2")

我希望能够做到的事情

XCTAssertEqual(app.staticTexts["myText"].label, "Expected 1")
sleep(20)
app.elements.refresh()
XCTAssertEqual(app.staticTexts["myText"].label, "Expected 2")

【问题讨论】:

  • 你能包含你正在使用的代码吗?您是在使用expectationForPredicatewaitForExpectationsWithTimeout 来等待,还是其他?
  • 话虽如此,我也是因为类似的问题才来到这里的。我正在做 myButton.tap() ,它在屏幕上移动按钮,然后 myButton 神秘地引用了一个不同的按钮,可能是由于缓存魔法
  • 在上面添加了代码。在你的情况下,我认为你有相反的问题。您点击一个合成事件的按钮,从而重新加载元素层次结构,以便在您点击按钮时清除缓存。

标签: xcode-ui-testing


【解决方案1】:

为了强制更新可访问性层次结构,请为任何XCUIElementQuery 请求count 属性:

// refresh
_ = XCUIApplication().navigationBars.count

// examine
print(XCUIApplication().debugDescription)

上面的结果是:“Get number of matches for: Descendants matching type NavigationBar”和“Snapshot accessibility hierarchy for com.myapp”。

【讨论】:

  • 谢谢。我正在使用这个助手使它方便(作为 XCUIElement 上的类别完成): [[[[XCUIApplication alloc] init] childrenMatchingType:XCUIElementTypeAny] count];
  • 它对我不起作用(Xcode9.3)。通常我的所有视图都在元素树中更新,除了极少数是自定义视图。我猜开发人员没有在自定义视图子类中的某些覆盖中调用一些超级方法,这些覆盖更新了树中存在的这些元素。这只是一个猜测。我可靠地处理此类元素的解决方法是返回并重新打开同一屏幕,现在元素树反映了屏幕上的实际元素。
【解决方案2】:

以下内容在 Xcode 10.2 (10E125) 中适用于我:

import XCTest

extension XCUIApplication {
    // WORKAROUND:
    // Force XCTest to update its accessibility cache. When accessibility data
    // like NSObject.accessibility{Label|Identifier} changes, it takes a while
    // for XCTest to catch up. Calling this method causes XCTest to update its
    // accessibility cache immediately.
    func updateAccessibilityCache() {
        _ = try? snapshot()
    }
}

【讨论】:

    【解决方案3】:

    您应该使用expectationForPredicate,类似于...

    let myText = app.staticTexts["myText"]
    let waitFor = NSPredicate(format: "label = 'Expected 2'")
    label.tap()
    self.expectationForPredicate(waitFor, evaluatedWithObject: myText, handler: nil)
    self.waitForExpectationsWithTimeout(2.0, handler: nil)
    

    这将等到 myText 的标签为“预期 2”,或者达到 2 秒的超时。

    【讨论】:

    • 问题是,从 Xcode 8.0 (iOS 10) 开始,如果您尝试 waitForExpectationsWithTimeout 导航栏(或其任何子级),XCUI 经常会崩溃,而导航控制器转换没有尚未完成。对于任何其他 UI 元素,例如显示的滚动视图或按钮,您必须首先 waitForExpectationsWithTimeout,然后才能为导航栏重新 XCUIElementQuery
    【解决方案4】:

    就我而言,这是一个问题,因为我正在尝试测试 Facebook 登录,它使用 Safari controller。看起来 Facebook 在缓存后更新了 UI。

    所以你需要wait一点,这里使用wait函数https://stackoverflow.com/a/42222302/1418457

    wait(for: 2)
    let _ = app.staticTexts.count
    

    但以上只是解决方法并且非常不稳定。更正确的做法是等待某个元素出现,见https://stackoverflow.com/a/44279203/1418457

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-31
      • 2021-11-17
      • 2015-07-01
      • 2022-01-19
      • 1970-01-01
      • 2016-04-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多