iOS XCUITests 按可访问性访问元素

iOS XCUITests access element by accessibility

如何通过 accessibilityLabel 或标识符断言按钮存在?

func testExitsButton() {
    XCTAssertTrue(app.windows.containing(.button, identifier: "Button Text").element.exists)
    XCTAssertTrue(app.buttons["Button Text"].exists)
    XCTAssertTrue(app.buttons["test"].exists) <- I want this, instead of accessing the text property I want by specific id, maybe the text property override the accessibilityLabel?
}

在您的应用程序代码中设置可访问性标识符,然后在您的测试中使用该标识符搜索按钮。

// app code
let button: UIButton!
button.accessibilityIdentifier = "myButton"

// UI test code
func testMyButtonIsDisplayed() {
    let app = XCUIApplication()
    let button = app.buttons["myButton"]
    XCTAssertTrue(button.exists)
}

辅助功能标识符的设置独立于按钮上的文本,也独立于辅助功能标签。将 UI 元素的标识符作为可访问性 标签 并不是最佳做法,因为向 VoiceOver 用户朗读可访问性标签以向他们解释该元素。

重要提示:如果超级视图设置为可访问,XCUITest 可能无法访问其子视图。

您可以通过情节提要或编程方式设置元素的可访问性来访问该元素,如上所述。当光标位于以前缀 "test" 开头的函数中时,您可以单击记录按钮,以记录 XCUITest 如何查看元素。有时需要几次清理(命令 shift k)和几分钟才能使用录制按钮。您还可以从情节提要中退出您的树并使用 XCUITest 函数,例如元素(boundBy:Int),children(匹配:.textField),您也可以链接它们:XCUIApplication()。tables.cells.containing(.button,标识符:"id")。之后是简单的部分,使用 .exists which returns 一个布尔值。

添加 | "accessibilityIdentifier" 字符串测试 |在导航栏上的用户定义的运行时属性中,而不是在可访问性标签中

我遇到了同样的问题,因为键盘盖住了按钮,所以:

app.buttons["Done"].tap()

解决了问题。

无障碍元素指南 ☑️

我在此答案中概述了一些与 iOS 代码库的可访问性相关的最相关的最佳实践,其中包含 UI 测试。请注意,即使此答案适用于 UIKit 应用程序,但相同的最佳实践在 SwiftUI 和 UIKit 之间是框架不可知的(仅具有不同的 API 名称)。

对 SwiftUI 可访问性视图修改器应用相同的推理,以确保两种类型的应用程序都具有良好的用户体验。

我强烈建议关注应用程序的辅助功能,因为 Apple 推广执行高辅助功能标准的应用程序,支持辅助功能是通过服务于更广泛的受众的更“道德”的软件开发。

使用.accessibilityIdentifier

我写这个答案是为了建议其他人/OP/comments不要仅仅为了启用UI测试而将.accessibilityLabel.accessibilityIdentifier互换使用。

使用 . accessibilityIdentifier 而不是 .accessibilityLabel,否则我们会为 VoiceOver 用户创造糟糕的用户体验:

button.accessibilityLabel = "test" // ❌

读给用户的是“Button.test”,如果用户有视力障碍,这不能帮助他们在屏幕上导航!

 button.accessibilityIdentifier = "test" // 

使用标识符意味着 VoiceOver 读取按钮的标题标签文本而不是“测试”。

注意:如果您仍然无法找到该元素,double-check 您还没有在故事板或 xib 文件的代码中覆盖 .accessibilityIdentifier 配置。还要检查按钮在两个地方都是无障碍元素。

启用 UI 容器视图中的按钮测试

您可能无法在 UI 测试中找到按钮,因为它是可访问元素的子视图。为了在按钮上启用 UI 测试和容器的 VoiceOver 的可访问性,请改用 .accessibilityElements

containerView = UIView()
containerView.isAccessibilityElement = false
containerView.accessibilityElements = [firstLabel, secondLabel, button]
// These elements are subviews of containerView

设置 .accessibilityElements 使 parent 视图成为辅助功能容器!这里的优势是我们得到 UI 测试以及可访问的 VoiceOver 用户体验,允许用户在子视图中 select/navigate。

屏幕阅读器按照元素出现的顺序浏览 page/screen 上的元素。设置您希望 VoiceOver 读取 .accessibilityElements 属性.

中的元素的顺序

.isHittable 在 UI 测试中

我们现在可以找到带有简单 XCUIElementQuery 下标的按钮:

XCTAssertTrue(app.buttons["test"].isHittable)

我建议使用 .isHittable,如 this answer, rather than .exists because it provides a more robust test. We can see why from the docs 中所述:

isHittable returns true if the element exists and can be clicked, tapped, or pressed at its current location. It returns false if the element does not exist, is offscreen, or is covered by another element.