如何找出(使用 XCTest UITest)在 tvOS AppleTV 的表格视图中具有焦点的单元格?

Posted

技术标签:

【中文标题】如何找出(使用 XCTest UITest)在 tvOS AppleTV 的表格视图中具有焦点的单元格?【英文标题】:How to find out the (using XCTest UITest) a cell that has a focus in a table view in tvOS AppleTV? 【发布时间】:2016-05-26 16:47:43 【问题描述】:

我正在尝试在 Apple TV (tvOS) 上自动执行应用的 UI 测试。

在登录屏幕上,我选择“输入用户名”字段。然后出现以前使用过的登录屏幕。在屏幕上,我想选择“清除所有”单元格。

澄清一下:“以前使用过”菜单似乎内置在 tvOS 中,每当有人在登录菜单中选择用户名文本字段时,它可能会自动出现。我不确定,所以我仍然需要确认该信息。

所以我认为这样的代码将是一个解决方案:

    if self.app.staticTexts["Previously Used"].exists 

        let clearAllCell = self.app.cells.staticTexts["Clear All"]

        while clearAllCell.hasFocus == false 
            XCUIRemote.sharedRemote().pressButton(.Down)
            sleep(1)
        

        XCUIRemote.sharedRemote().pressButton(.Select)
    

但是即使是这样的状态:

单元格的属性hasFocusselected 似乎返回false:

po self.app.cells.staticTexts["Clear All"].hasFocus
po self.app.cells.staticTexts["Clear All"].selected

当单元格处于“聚焦状态”时,如何找到“清除所有”单元格?

更新:

我尝试了@Oletha 提出的解决方案,但没有成功。不幸的是,clearAllCell.hasFocus 似乎总是返回 false。

    if self.app.staticTexts["Previously Used"].exists 

        let clearAllCell = self.app.cells.staticTexts["Clear All"]

        let predicateHasFocus = NSPredicate(format: "exists == true", argumentArray: nil)

        expectationForPredicate(predicateHasFocus, evaluatedWithObject: clearAllCell, handler:  () -> Bool in
            if clearAllCell.hasFocus 
                return true
             else 
                sleep(1)
                XCUIRemote.sharedRemote().pressButton(.Down)
                return false
            
        )

        waitForExpectationsWithTimeout(10, handler: nil)

        XCUIRemote.sharedRemote().pressButton(.Select)
    

更新:

目前一个不优雅的解决方案是:

    if self.app.staticTexts["Previously Used"].exists 
        var cellsCount = self.app.cells.count

        // Select Clear All menu button, hack as it was not possible to detect "Clear All" cell in another way
        while cellsCount > 0 
            sleep(1)
            XCUIRemote.sharedRemote().pressButton(.Down)
            cellsCount -= 1
        

        sleep(1)
        XCUIRemote.sharedRemote().pressButton(.Up)
        sleep(1)
        XCUIRemote.sharedRemote().pressButton(.Select)
    

【问题讨论】:

直接访问静态文本有区别吗?例如app.staticTexts["Clear All"].hasFocus 很遗憾没有,po app.staticTexts["Clear All"].hasFocuspo app.staticTexts["Clear All"].selected 仍然返回 false。 嗯。为什么它们首先是细胞?它们可以轻松迁移到按钮吗?我有一个使用按钮和hasFocus 没有问题的应用程序。 我认为“以前使用过”的整个菜单是 tvOS 原生的,因此可能没有简单的方法可以迁移到按钮。我试过 po app.buttons.staticTexts["Clear All"].exists 但它返回 false。 这看起来像是我遇到的一个问题,其中单元格本身是一个可访问性元素,因此检查员看不到它的后代。您是否尝试过在单元格本身上放置一个可访问性标识符并将其称为 app.cells[" 【参考方案1】:

我的应用遇到了类似的问题,发现有两点有助于编写运行 UI 测试:

    每次按下远程按钮后总是延迟 1 秒,因为断言评估通常比焦点更改更快,因此返回 false

    XCUIRemote.sharedRemote().pressButton(.Down)
    sleep(1)
    

    查找焦点元素的确切 UI 层次结构位置。例如,print(XCUIApplication().debugDescription) 将为您提供详细的 UI 树,并且可以轻松正确地访问您的元素。

此断言返回 true:

    XCTAssert(XCUIApplication().tabBars.buttons["Home"].hasFocus)

【讨论】:

【参考方案2】:

使用expectationForPredicatewaitForExpectationsWithTimeout 检查单元格是否有焦点。使用期望会导致每次检查发生时刷新可访问性层次结构快照。您的 while 循环每次都检查相同的缓存层次结构快照,因此结果不会改变。

let app = XCUIApplication()
let clearAllCell = app.cells.staticTexts["Clear All"]
let focusedPredicate = NSPredicate(format: "exists == true")
let remote = XCUIRemote.sharedRemote()

expectationForPredicate(focusedPredicate, evaluatedWithObject: clearAllCell, handler: () -> Bool in
    // Check if the cell has focus
    if clearAllCell.hasFocus 
        // Fulfill the expectation
        return true
     else 
        // Move down one cell before the next check
        remote.pressButton(.Down)
        return false
    
)
waitForExpectationsWithTimeout(5, handler: nil)

remote.pressButton(.Select)

XCUIRemote.sharedRemote() 实际上对我没有用,但我猜这对你有用 - 我没有 Apple TV 应用程序可供测试。

【讨论】:

您能否通过重构问题中的不成功解决方案来提供代码示例?我尝试使用expectationForPredicatewaitForExpectationsWithTimeout 来实现,但没有成功。 @tommagellancook 用我认为应该有帮助的示例更新了答案。 我已经尝试过您的代码,但它看起来不像它应该的那样工作。循环正在检查 clearAll 是否具有焦点,但它永远不会返回 true。我已经更新了我的问题,以便您可以在代码中达到峰值。【参考方案3】:

首先,它是 tvOS 中的本机屏幕,因此所有与尝试设置辅助功能 ID 相关的建议都不相关。当你到达那个屏幕并打印出哪个元素被聚焦时尝试放置一个断点

我相信答案会是。屏幕上的一个位置。或没有标识符的单元格。我在 Apple TV 上遇到了同样的问题,我想知道你遇到的所有问题,因为我想知道 xcuitest 对于 tvOS 有多成熟

【讨论】:

以上是关于如何找出(使用 XCTest UITest)在 tvOS AppleTV 的表格视图中具有焦点的单元格?的主要内容,如果未能解决你的问题,请参考以下文章

打印到 Xcode (XCTest) UITest 报告

如何创建一个在 XCTest 中定义按钮或文本字段的 swift 文件?

UITest 在框架中不起作用

如何确保我的 Xcode UITest 目标仅构建目标应用程序?

Xcode 9 UITest 不工作

带有本地化 app.staticTexts 的 UI 测试 (XCTest)