基于 UIHierarchy 创建 UIElementQuery
Creating a UIElementQuery based off of a UIHierarchy
我有一个分层 UI,我正在尝试为其创建一个 UI 测试。我在工作时对 UI 的构造方式没有深入了解,但我可以完全访问源代码。
我正在尝试点击弹出的按钮以 "Confirm" 删除特定条目。但是,我无法在 Swift 中创建一个查询来让我点击正确的按钮。这是错误的完整转储:
UI Test Activity:
Assertion Failure: ProfileScreen.swift:77: Failed to get matching snapshot: Multiple matching elements found for <XCUIElementQuery: 0x6000007c4d20>.
Sparse tree of matches:
→Application, pid: 92707, label: '******'
↳Window (Main)
⋅ ↳Other
⋅ ↳Other
⋅ ↳Button, identifier: 'Remove', label: 'Remove'
↳Window
↳Other
↳Other
↳Other
↳Other
↳Other
↳Other
↳Other
↳Other
↳Other
↳Other
↳Other
↳Other
↳CollectionView
↳Cell, Selected
⋅ ↳Other
⋅ ↳Button, label: 'Remove'
↳Cell
↳Other
↳Button, label: 'Remove'
Possibly caused by runtime issues:
Automation type mismatch: computed Other from legacy attributes vs StaticText from modern attribute. Input attributes and values: {
"XC_kAXXCAttributeAutomationType" = 48;
"XC_kAXXCAttributeElementBaseType" = UILabel;
"XC_kAXXCAttributeElementType" = UILabel;
"XC_kAXXCAttributeTraits" = 8590000128;
}
See test report attachments for more detail.
我必须生成该错误的查询是这样的:
XCUIApplication().buttons["Remove"].tap()
而实际的UI层次结构:
Window, {{0.0, 0.0}, {414.0, 896.0}}
Other, {{0.0, 0.0}, {414.0, 896.0}}
Other, {{0.0, 0.0}, {414.0, 896.0}}
Other, {{0.0, 0.0}, {414.0, 896.0}}
Other, {{0.0, 0.0}, {414.0, 896.0}}
Other, {{0.0, 0.0}, {414.0, 896.0}}
Other, {{0.0, 0.0}, {414.0, 896.0}}
Other, {{0.0, 0.0}, {414.0, 896.0}}
Other, {{0.0, 0.0}, {414.0, 896.0}}
NavigationBar, {{0.0, 44.0}, {414.0, 44.0}}, identifier: 'Payment Information'
Button, {{0.0, 44.0}, {44.0, 44.0}}, label: 'Settings'
StaticText, {{139.5, 58.5}, {135.0, 17.0}}, label: 'Payment Information'
Other, {{0.0, 0.0}, {414.0, 896.0}}
Other, {{0.0, 0.0}, {414.0, 896.0}}
Other, {{0.0, 88.0}, {414.0, 808.0}}
Other, {{0.0, 88.0}, {414.0, 808.0}}
CollectionView, {{0.0, 88.0}, {414.0, 808.0}}
Cell, {{0.0, 88.0}, {414.0, 72.0}}, Selected
Other, {{0.0, 88.0}, {414.0, 72.0}}
Image, {{24.0, 115.0}, {18.0, 18.0}}
Image, {{58.0, 110.0}, {49.5, 28.0}}
StaticText, {{123.5, 114.5}, {36.0, 19.5}}, label: '1111'
Button, {{331.0, 108.5}, {59.0, 31.0}}, label: 'Remove'
StaticText, {{331.0, 114.5}, {59.0, 19.0}}, label: 'Remove'
Other, {{0.0, 159.5}, {414.0, 0.5}}
Cell, {{0.0, 160.0}, {414.0, 72.0}}
Other, {{0.0, 160.0}, {414.0, 72.0}}
Image, {{24.0, 187.0}, {18.0, 18.0}}
Image, {{58.0, 182.0}, {49.5, 28.0}}
StaticText, {{123.5, 186.5}, {36.0, 19.5}}, label: '2222'
Button, {{331.0, 180.5}, {59.0, 31.0}}, label: 'Remove'
StaticText, {{331.0, 186.5}, {59.0, 19.0}}, label: 'Remove'
Other, {{0.0, 231.5}, {414.0, 0.5}}
Cell, {{0.0, 232.0}, {414.0, 72.0}}
Other, {{0.0, 232.0}, {414.0, 72.0}}
Image, {{24.0, 259.0}, {18.0, 18.0}}
Other, {{58.0, 254.0}, {49.5, 28.0}}
Button, {{64.2, 257.5}, {37.1, 21.0}}, label: 'Buy with Touch Pay'
StaticText, {{64.2, 257.5}, {0.0, 0.0}}
StaticText, {{123.5, 258.5}, {75.5, 19.5}}, label: 'Touch Pay'
Other, {{0.0, 303.5}, {414.0, 0.5}}
Cell, {{0.0, 304.0}, {414.0, 166.0}}
Other, {{0.0, 304.0}, {414.0, 166.0}}
Button, {{16.0, 328.0}, {382.0, 60.0}}, label: 'Add New Item'
StaticText, {{107.5, 348.0}, {199.0, 20.0}}, label: 'Add New Item'
Other, {{381.0, 105.5}, {30.0, 755.5}}, label: 'Vertical scroll bar, 1 page', value: 0%
Other, {{35.0, 863.0}, {344.0, 30.0}}, label: 'Horizontal scroll bar, 1 page', value: 0%
Other, {{0.0, 840.0}, {414.0, 56.0}}
Other, {{0.0, 840.0}, {414.0, 0.5}}
Other, {{0.0, 840.0}, {414.0, 56.0}}
Button, {{0.0, 840.0}, {103.5, 56.0}}, identifier: 'tab_bar_title-main', label: 'Main'
Button, {{103.5, 840.0}, {103.5, 56.0}}, identifier: 'tab_bar_title-secondary', label: 'Secondary'
Button, {{207.0, 840.0}, {103.5, 56.0}}, identifier: 'tab_bar_title-todo', label: 'Todo'
Button, {{310.5, 840.0}, {103.5, 56.0}}, identifier: 'tab_bar_title-whatsup', label: 'Whatsup', Selected
Window, {{0.0, 0.0}, {414.0, 896.0}}
Other, {{0.0, 0.0}, {414.0, 896.0}}
Other, {{0.0, 0.0}, {414.0, 896.0}}
Other, {{0.0, 896.0}, {414.0, 243.0}}
Window (Main), {{0.0, 0.0}, {414.0, 896.0}}
Other, {{0.0, 0.0}, {414.0, 896.0}}
Other, {{0.0, 0.0}, {414.0, 896.0}}
Other, {{67.0, 350.0}, {280.0, 196.5}}
StaticText, {{101.0, 384.0}, {212.0, 24.0}}, label: 'Remove Item'
StaticText, {{101.0, 424.0}, {212.0, 38.0}}, label: 'Do you want to remove the Item?'
Other, {{67.0, 486.0}, {280.0, 0.5}}
Button, {{67.0, 486.5}, {140.0, 60.0}}, identifier: 'Cancel', label: 'Cancel'
StaticText, {{112.0, 507.0}, {50.0, 19.0}}, label: 'Cancel'
Other, {{207.0, 486.0}, {0.5, 60.5}}
Button, {{207.5, 486.5}, {139.5, 60.0}}, identifier: 'Remove', label: 'Remove'
StaticText, {{247.0, 506.5}, {61.0, 20.0}}, label: 'Remove'
Other, {{0.0, 0.0}, {414.0, 896.0}}
Other, {{0.0, 0.0}, {414.0, 896.0}}
所以它显然找到了这两个按钮。有两个具有相同 staticText 和 Label 的按钮。有没有一种方法可以让我轻松点按已启用或具有当前焦点的那个?
我也很好奇是否有办法将 UI 层次结构转储告诉我的内容转换为可行的查询。
您通常可以 select 唯一、第一个、第 N 个或最后一个按钮。
首次使用:
let app = XCUIApplication()
app.buttons["Remove"].tap() // the only
app.buttons["Remove"].element.tap() // the only
app.buttons["Remove"].firstMatch.tap() // the first
app.buttons["Remove"].element(boundBy: 3) // the fourth
app.buttons.matching(identifier: "Remove").lastMatch.tap() // the last
最后一个查询需要扩展:
extension XCUIElementQuery {
var lastMatch: XCUIElement { return self.element(boundBy: self.count - 1) }
}
在此处阅读有关其他查询的更多信息:https://developer.apple.com/documentation/xctest/xcuielementquery
您也可以尝试使用 https://github.com/forqa/skeleton 等工具为您生成元素列表
在你的代码中
而不是 XCUIApplication().buttons["Remove"].tap()
放这个XCUIApplication().buttons["Remove"].firstMatch.tap()
或
您可以使用 query 获取第一个元素
XCUIApplication().buttons.matching(identifier: "Remove").element(boundBy: 0).tap()
或第二个元素
XCUIApplication().buttons.matching(identifier: "Remove").element(boundBy: 1).tap()
我有一个分层 UI,我正在尝试为其创建一个 UI 测试。我在工作时对 UI 的构造方式没有深入了解,但我可以完全访问源代码。
我正在尝试点击弹出的按钮以 "Confirm" 删除特定条目。但是,我无法在 Swift 中创建一个查询来让我点击正确的按钮。这是错误的完整转储:
UI Test Activity:
Assertion Failure: ProfileScreen.swift:77: Failed to get matching snapshot: Multiple matching elements found for <XCUIElementQuery: 0x6000007c4d20>.
Sparse tree of matches:
→Application, pid: 92707, label: '******'
↳Window (Main)
⋅ ↳Other
⋅ ↳Other
⋅ ↳Button, identifier: 'Remove', label: 'Remove'
↳Window
↳Other
↳Other
↳Other
↳Other
↳Other
↳Other
↳Other
↳Other
↳Other
↳Other
↳Other
↳Other
↳CollectionView
↳Cell, Selected
⋅ ↳Other
⋅ ↳Button, label: 'Remove'
↳Cell
↳Other
↳Button, label: 'Remove'
Possibly caused by runtime issues:
Automation type mismatch: computed Other from legacy attributes vs StaticText from modern attribute. Input attributes and values: {
"XC_kAXXCAttributeAutomationType" = 48;
"XC_kAXXCAttributeElementBaseType" = UILabel;
"XC_kAXXCAttributeElementType" = UILabel;
"XC_kAXXCAttributeTraits" = 8590000128;
}
See test report attachments for more detail.
我必须生成该错误的查询是这样的:
XCUIApplication().buttons["Remove"].tap()
而实际的UI层次结构:
Window, {{0.0, 0.0}, {414.0, 896.0}}
Other, {{0.0, 0.0}, {414.0, 896.0}}
Other, {{0.0, 0.0}, {414.0, 896.0}}
Other, {{0.0, 0.0}, {414.0, 896.0}}
Other, {{0.0, 0.0}, {414.0, 896.0}}
Other, {{0.0, 0.0}, {414.0, 896.0}}
Other, {{0.0, 0.0}, {414.0, 896.0}}
Other, {{0.0, 0.0}, {414.0, 896.0}}
Other, {{0.0, 0.0}, {414.0, 896.0}}
NavigationBar, {{0.0, 44.0}, {414.0, 44.0}}, identifier: 'Payment Information'
Button, {{0.0, 44.0}, {44.0, 44.0}}, label: 'Settings'
StaticText, {{139.5, 58.5}, {135.0, 17.0}}, label: 'Payment Information'
Other, {{0.0, 0.0}, {414.0, 896.0}}
Other, {{0.0, 0.0}, {414.0, 896.0}}
Other, {{0.0, 88.0}, {414.0, 808.0}}
Other, {{0.0, 88.0}, {414.0, 808.0}}
CollectionView, {{0.0, 88.0}, {414.0, 808.0}}
Cell, {{0.0, 88.0}, {414.0, 72.0}}, Selected
Other, {{0.0, 88.0}, {414.0, 72.0}}
Image, {{24.0, 115.0}, {18.0, 18.0}}
Image, {{58.0, 110.0}, {49.5, 28.0}}
StaticText, {{123.5, 114.5}, {36.0, 19.5}}, label: '1111'
Button, {{331.0, 108.5}, {59.0, 31.0}}, label: 'Remove'
StaticText, {{331.0, 114.5}, {59.0, 19.0}}, label: 'Remove'
Other, {{0.0, 159.5}, {414.0, 0.5}}
Cell, {{0.0, 160.0}, {414.0, 72.0}}
Other, {{0.0, 160.0}, {414.0, 72.0}}
Image, {{24.0, 187.0}, {18.0, 18.0}}
Image, {{58.0, 182.0}, {49.5, 28.0}}
StaticText, {{123.5, 186.5}, {36.0, 19.5}}, label: '2222'
Button, {{331.0, 180.5}, {59.0, 31.0}}, label: 'Remove'
StaticText, {{331.0, 186.5}, {59.0, 19.0}}, label: 'Remove'
Other, {{0.0, 231.5}, {414.0, 0.5}}
Cell, {{0.0, 232.0}, {414.0, 72.0}}
Other, {{0.0, 232.0}, {414.0, 72.0}}
Image, {{24.0, 259.0}, {18.0, 18.0}}
Other, {{58.0, 254.0}, {49.5, 28.0}}
Button, {{64.2, 257.5}, {37.1, 21.0}}, label: 'Buy with Touch Pay'
StaticText, {{64.2, 257.5}, {0.0, 0.0}}
StaticText, {{123.5, 258.5}, {75.5, 19.5}}, label: 'Touch Pay'
Other, {{0.0, 303.5}, {414.0, 0.5}}
Cell, {{0.0, 304.0}, {414.0, 166.0}}
Other, {{0.0, 304.0}, {414.0, 166.0}}
Button, {{16.0, 328.0}, {382.0, 60.0}}, label: 'Add New Item'
StaticText, {{107.5, 348.0}, {199.0, 20.0}}, label: 'Add New Item'
Other, {{381.0, 105.5}, {30.0, 755.5}}, label: 'Vertical scroll bar, 1 page', value: 0%
Other, {{35.0, 863.0}, {344.0, 30.0}}, label: 'Horizontal scroll bar, 1 page', value: 0%
Other, {{0.0, 840.0}, {414.0, 56.0}}
Other, {{0.0, 840.0}, {414.0, 0.5}}
Other, {{0.0, 840.0}, {414.0, 56.0}}
Button, {{0.0, 840.0}, {103.5, 56.0}}, identifier: 'tab_bar_title-main', label: 'Main'
Button, {{103.5, 840.0}, {103.5, 56.0}}, identifier: 'tab_bar_title-secondary', label: 'Secondary'
Button, {{207.0, 840.0}, {103.5, 56.0}}, identifier: 'tab_bar_title-todo', label: 'Todo'
Button, {{310.5, 840.0}, {103.5, 56.0}}, identifier: 'tab_bar_title-whatsup', label: 'Whatsup', Selected
Window, {{0.0, 0.0}, {414.0, 896.0}}
Other, {{0.0, 0.0}, {414.0, 896.0}}
Other, {{0.0, 0.0}, {414.0, 896.0}}
Other, {{0.0, 896.0}, {414.0, 243.0}}
Window (Main), {{0.0, 0.0}, {414.0, 896.0}}
Other, {{0.0, 0.0}, {414.0, 896.0}}
Other, {{0.0, 0.0}, {414.0, 896.0}}
Other, {{67.0, 350.0}, {280.0, 196.5}}
StaticText, {{101.0, 384.0}, {212.0, 24.0}}, label: 'Remove Item'
StaticText, {{101.0, 424.0}, {212.0, 38.0}}, label: 'Do you want to remove the Item?'
Other, {{67.0, 486.0}, {280.0, 0.5}}
Button, {{67.0, 486.5}, {140.0, 60.0}}, identifier: 'Cancel', label: 'Cancel'
StaticText, {{112.0, 507.0}, {50.0, 19.0}}, label: 'Cancel'
Other, {{207.0, 486.0}, {0.5, 60.5}}
Button, {{207.5, 486.5}, {139.5, 60.0}}, identifier: 'Remove', label: 'Remove'
StaticText, {{247.0, 506.5}, {61.0, 20.0}}, label: 'Remove'
Other, {{0.0, 0.0}, {414.0, 896.0}}
Other, {{0.0, 0.0}, {414.0, 896.0}}
所以它显然找到了这两个按钮。有两个具有相同 staticText 和 Label 的按钮。有没有一种方法可以让我轻松点按已启用或具有当前焦点的那个?
我也很好奇是否有办法将 UI 层次结构转储告诉我的内容转换为可行的查询。
您通常可以 select 唯一、第一个、第 N 个或最后一个按钮。
首次使用:
let app = XCUIApplication()
app.buttons["Remove"].tap() // the only
app.buttons["Remove"].element.tap() // the only
app.buttons["Remove"].firstMatch.tap() // the first
app.buttons["Remove"].element(boundBy: 3) // the fourth
app.buttons.matching(identifier: "Remove").lastMatch.tap() // the last
最后一个查询需要扩展:
extension XCUIElementQuery {
var lastMatch: XCUIElement { return self.element(boundBy: self.count - 1) }
}
在此处阅读有关其他查询的更多信息:https://developer.apple.com/documentation/xctest/xcuielementquery
您也可以尝试使用 https://github.com/forqa/skeleton 等工具为您生成元素列表
在你的代码中
而不是 XCUIApplication().buttons["Remove"].tap()
放这个XCUIApplication().buttons["Remove"].firstMatch.tap()
或
您可以使用 query 获取第一个元素
XCUIApplication().buttons.matching(identifier: "Remove").element(boundBy: 0).tap()
或第二个元素
XCUIApplication().buttons.matching(identifier: "Remove").element(boundBy: 1).tap()