XCTest 无法访问屏幕上的错误消息标签

ann*_*101 0 ios xctest xcode-ui-testing xcode8

背景资料:

\n

我需要为简单的应用程序屏幕编写一些 UI 测试,该屏幕顶部有一个导航栏,屏幕其余部分有一个包含两个单元格的表格。

\n

每个单元格包含:

\n
    \n
  • 标签(“会员卡号”)
  • \n
  • 用于输入的安全文本字段
  • \n
  • 安全字段下的标签(“您必须在此处放置\n10 位会员卡号”)
  • \n
  • 仅当用户输入的位数少于或多于所需位数时,才会在输入字段下显示可选的错误文本
  • \n
\n

这是一张图像,可让您了解屏幕上的元素\n图像

\n

目标:

\n

编写一个测试执行以下操作:

\n
    \n
  • 点击卡片输入字段
  • \n
  • 输入无效的卡号(假设是 12 位数字而不是 10 位)
  • \n
  • 检查该字段下是否出现错误消息
  • \n
\n

问题:

\n

XCTest 无法识别包含错误的元素。

\n

当我使用调试视图层次结构检查元素时,它就在那里,清晰可见,文本属性“不能少于或超过 10 位数字”,accessibiltyIndentifier“errorField”。

\n

层次结构: UIWindow->UILayoutContainerView->UINavigationTransitionView->UIViewControllerWrapperView->UIView->Form->FormTextFieldCell->UITableViewCellContentView->UIView->UILabel

\n

它有一个同级,也是 UILabel(“这是您必须放置 10 位会员卡的地方”) - 访问这个同级没有问题。我可以通过accessibilityIdentifier或其文本访问它:

\n
app.staticTexts["hintField"]\napp.staticTexts["This is where you must put your 10-digit loyalty card"]\n
Run Code Online (Sandbox Code Playgroud)\n

但这些选项都不适用于我感兴趣的元素。当我打印 app.debugDescription 时,该元素不存在,就好像它不存在一样。

\n

以下是用户输入错误并且错误文本已在屏幕上可见后 debugDescription 的输出:

\n
Element subtree:\n \xe2\x86\x92Application 0x60000016e700: {{0.0, 0.0}, {414.0, 736.0}}, label: \xe2\x80\x98test-app\xe2\x80\x99\nWindow 0x60000016e7c0: Main Window, {{0.0, 0.0}, {414.0, 736.0}}\n  Other 0x60000016e4c0: traits: 8589934592, {{0.0, 0.0}, {414.0, 736.0}}\n    NavigationBar 0x60000016e580: traits: 35192962023424, {{0.0, 20.0}, {414.0, 44.0}}, identifier: \xe2\x80\x98Card Info Screen\xe2\x80\x99\n      Button 0x60000016e880: traits: 8589934593, {{20.0, 26.7}, {53.0, 30.0}}, label: \xe2\x80\x98Back\xe2\x80\x99\n      StaticText 0x60000016eac0: traits: 8590000192, {{158.7, 28.0}, {97.0, 27.0}}, label: \xe2\x80\x98Next\xe2\x80\x99\n      Button 0x60000016ea00: traits: 8589934849, {{356.0, 26.7}, {38.0, 30.0}}, label: \xe2\x80\x98Next\xe2\x80\x99\n    Other 0x60000016e940: traits: 8589934592, {{0.0, 0.0}, {414.0, 736.0}}\n      Other 0x60000016ed00: traits: 8589934592, {{0.0, 0.0}, {414.0, 736.0}}\n        Other 0x60000016edc0: traits: 8589934592, {{0.0, 64.0}, {414.0, 672.0}}\n          Other 0x60000016ee80: traits: 8589934592, {{0.0, 64.0}, {414.0, 48.0}}\n            StaticText 0x60000016eb80: traits: 8589934656, {{24.0, 79.0}, {366.0, 18.0}}, label: \xe2\x80\x98Enter your loyalty card information.\xe2\x80\x99\n          Table 0x60000016ef40: traits: 35192962023424, {{0.0, 112.0}, {414.0, 573.0}}\n            Cell 0x60000016ec40: traits: 8589934592, {{0.0, 112.0}, {414.0, 67.0}}\n              StaticText 0x60000016f000: traits: 8589934656, {{16.0, 123.3}, {96.3, 18.0}}, label: \xe2\x80\x98Your loyalty card nr\xe2\x80\x99\n              StaticText 0x60000016f0c0: traits: 8589934656, {{16.0, 158.7}, {390.0, 13.7}}, identifier: \xe2\x80\x98hintField\xe2\x80\x99, label: \xe2\x80\x98This is where you must put your 10-digit loyalty card.\xe2\x80\x99\n              SecureTextField 0x60000016f180: traits: 8609071104, Keyboard Focused, {{119.3, 122.0}, {286.7, 20.0}}, identifier: \xe2\x80\x98editField\xe2\x80\x99, value: \xe2\x80\xa2\xe2\x80\xa2\xe2\x80\xa2\xe2\x80\xa2\xe2\x80\xa2\xe2\x80\xa2\xe2\x80\xa2\xe2\x80\xa2\xe2\x80\xa2\xe2\x80\xa2\xe2\x80\xa2\xe2\x80\xa2\n            Cell 0x60000016f240: traits: 8589934592, {{0.0, 179.0}, {414.0, 53.0}}\n              StaticText 0x60000016f300: traits: 8589934656, {{16.0, 189.0}, {100.7, 18.0}}, label: \xe2\x80\x98Birthday\xe2\x80\x99\n              StaticText 0x60000016f3c0: traits: 8589934656, {{16.0, 210.0}, {390.0, 13.7}}, identifier: \xe2\x80\x98hintField\xe2\x80\x99, label: \xe2\x80\x98Please enter your birthday in DDMMYYYY format\xe2\x80\x99\n              SecureTextField 0x60000016f480: traits: 8606973952, {{123.7, 189.0}, {282.3, 18.0}}, identifier: \xe2\x80\x98editField\xe2\x80\x99, placeholderValue: \xe2\x80\x98********\xe2\x80\x99\n            Cell 0x60000016f540: traits: 8589934592, {{0.0, 232.0}, {414.0, 70.0}}\n          Other 0x60000016f600: traits: 8589934592, {{0.0, 685.0}, {414.0, 51.0}}\n            StaticText 0x60000016f6c0: traits: 8589934656, {{112.0, 685.0}, {190.0, 15.7}}, label: \xe2\x80\x98Don\'t have a loyalty card yet?\xe2\x80\x99\n            Button 0x60000016f780: traits: 8589934593, {{162.7, 705.7}, {90.0, 22.3}}, label: \xe2\x80\x98Get one in one of our stores!\xe2\x80\x99\n
Run Code Online (Sandbox Code Playgroud)\n

当我尝试使用测试记录器时,以任何方式与错误交互都会导致:\n“时间戳事件匹配错误:无法找到匹配元素”。

\n

我应该注意到,测试记录器对于屏幕上的任何其他元素都没有这个问题。他无法记录点击的唯一元素是错误消息。他无法对第一个带有会员卡的单元格执行此操作,他也无法对带有生日的第二个单元格执行此操作。

\n

我尝试通过以下方式访问这个难以捉摸的元素:

\n
app.staticTexts["ACCESSIBILITY_ID"]\napp.staticTexts["ELEMENTS_TEXT]\napp.cells.containing(.staticText, identifier: "ACCESSIBILITY_ID_OF_PARENT").otherElements.element\n
Run Code Online (Sandbox Code Playgroud)\n

不幸的是,到目前为止没有任何效果。

\n

我因其他测试而受阻,变得非常绝望。

\n

任何帮助、任何建议都将受到高度赞赏!

\n

Cha*_*and 5

首先要检查的是辅助功能框架是否可以看到该元素。要查看辅助功能看到的内容,请启动您的应用程序并通过以下方式打开辅助功能检查器:

Xcode -> Open Developer Tool -> Accessibility Inspector
Run Code Online (Sandbox Code Playgroud)

然后,选择左上角目标列表下的模拟器,并选择右上角的目标十字线。将鼠标悬停在您要检查的标签上。这将向您显示辅助功能值和标签(在 Xcode 9 中还显示标识符)。如果辅助功能检查器看不到它,则说明代码中标签的设置方式存在问题,这意味着 Voice Over 用户也不会看到该标签。


由于您现有的 XCUITest 层次结构显示了 UITableViewCell 的内容,因此我们可以排除该单元格是一个离散的可访问性元素(这会隐藏 XCUITest /可访问性的子视图。不过,您可以检查该单元格是否标记为可访问性元素。 UIView 标志是isAccessibilityElement = true。您还可以检查开发人员是否将其设置为 true ,然后设置可访问的子视图:

myCell.accessibilityElements = [inputTextField, label1, label2] // left out error label, hence it's not accessible
Run Code Online (Sandbox Code Playgroud)

如果您担心层次结构可能不会刷新,您可以尝试通过以下方式告诉它在错误视图出现后刷新:

UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, myErrorLabel);
Run Code Online (Sandbox Code Playgroud)

当错误出现时,它也会将辅助功能焦点切换到该错误。(有关发布辅助功能通知的更多信息:https ://developer.apple.com/documentation/uikit/accessibility/uiaccessibility )