[使用最新版本的Xcode 11在iOS 13上运行,我找不到在XCTest UI测试中区分标题和静态文本的方法。
[如果我使用Xcode 11但在iOS 12上运行,我仍然能够通过使用XCTest按.header
元素类型进行过滤来查找具有.other
特征的视图,但是在iOS 13上具有.header
特征的视图是现在,即使您未在应用程序中设置.staticText
可访问性特征,也只是通过XCTest由.staticText
元素类型标识。
这给我们带来了问题,因为我们使用它来确保记住要在视图上正确设置标头特征以实现可访问性,并能够确保在测试中查看正确的屏幕。
诚然,只能通过.other
查找标头并不好,但是至少这是将标头与常规文本区分开的一种方式。
这里有一些示例代码来说明:
// ViewController.swift
headerLabel.isAccessibilityElement = true // headerLabel is just a UILabel IBOutlet
headerLabel.accessibilityTraits = [.header]
headerLabel.text = "My Header"
// ViewControllerTests.swift
XCTAssertTrue(XCUIApplication().otherElements["My Header"].firstMatch.waitForExistence(timeout: 30)) // This fails on iOS 13 but works on iOS 12 :(
XCTAssertTrue(XCUIApplication().staticTexts["My Header"].firstMatch.waitForExistence(timeout: 30)) // This fails on iOS 12 but works on iOS 13...
如果在Xcode中使用po XCUIApplication()
,则可以看到在iOS 13上,标头现在与其他所有标签都只是staticText
。
我已经尝试结合不同的accessibilityTraits(因为您可以拥有多个),例如:
headerLabel.accessibilityTraits = [.header, .staticText]
但是那没有帮助。
[好吧,经过几天的调查,我们有了一个解决方法。不幸的是,它使用了私有API,但是我们并不担心,因为它用于测试,并且比到目前为止我们尝试过的任何其他解决方法都要好。
使用私有API,可以找出UIAccessibilityTraits
表示的视图的基础XCUIElement
:
var underlyingAccessibilityTraits: UIAccessibilityTraits {
guard let rawValue = value(forKey: "traits") as? UInt64 else { return [] }
return UIAccessibilityTraits(rawValue: rawValue)
}
现在我们有了特征,我们可以像查询其他任何特征一样OptionSet
:
element.underlyingAccessibilityTraits.contains(.header)
而且我们可以使用它来构建自己的查询,而不是使用XCUIElementQuery
:
let allElementsMatchingID = XCUIApplication().descendants(matching: .any).matching(.any, identifier: id) // id is an optional string as an ID, like when using `XCUIApplication().otherElements[id]`
let allHeaders = allElementsMatchingID.allElementsBoundByAccessibilityElement.filter { $0.underlyingAccessibilityTraits.contains(.header) }
let element = allHeaders[index] // index is an int, like when using `element(boundBy: 0`
缺点(除了必须使用私有API之外,是不同于常规XCUIElementQuery
的问题,如果索引超出范围,则将崩溃,但是如果您始终期望该元素存在,则不是)很大。
您可以在标题的accessibilityIdentifier
中添加前缀,以将其与静态文本区分开,例如:
myHeader.accessibilityIdentifier = "Header" + title
并且只需使用与以前相同的静态文本
myLabel.accessibilityIdentifier = title