使用 XCUIElementQuery 在 SwiftUI 中查找嵌入在表单中的 DatePicker() 的可访问性(标识符:)

Posted

技术标签:

【中文标题】使用 XCUIElementQuery 在 SwiftUI 中查找嵌入在表单中的 DatePicker() 的可访问性(标识符:)【英文标题】:Finding the accessibility(identifier:) of DatePicker() embedded in a Form in SwiftUI using an XCUIElementQuery 【发布时间】:2020-07-18 14:22:53 【问题描述】:

我有一个 SwiftUI 视图,它有一个包含 DatePicker 的表单:

struct GettingUpTimeSettingView: View 
    @State private var viewModel = GettingUpTimeSettingViewModel()
    var body: some View 
        VStack 
            
            Form 
                Spacer()
                Text(viewModel.questionString)
                    .accessibility(identifier: "Question")
                Spacer()
                DatePicker("Alarm Time",
                                     selection: $viewModel.gettingUpTime,
                                     displayedComponents: .hourAndMinute)
                    .accessibility(identifier: "Time")
                    .animation(.easeInOut)
                Spacer()
                Text(viewModel.explanationString)
                    .accessibility(identifier: "Explanation")
            
        
    

还有一个用于 UI 测试的 XCTestCase 类:

class SleepyGPIntroUITests: XCTestCase 
    
    private var app: XCUIApplication!
    
    override func setUp() 
        continueAfterFailure = false
        app = XCUIApplication()
        app.launch()
        greeting = app.staticTexts["Greeting"]
    
    
    override func tearDown() 
        app = nil
    
    
    func test_InitialScreen_ChangesTo_GettingUpScreen_Automatically() 
        //Given
        let questionText = "What time do you want to get up?"
        let explanationText = "This should be the same time every day, including at weekends and on days off. Our best chance of great sleep comes when we have a regular routine."
        let timeText = "7:00am"
        let question = app.staticTexts["Question"]
        let explanation = app.staticTexts["Explanation"]
        let time = app.staticTexts["Time"]
        //When
        _ = time.waitForExistence(timeout: 2)
        //Then
        XCTAssertFalse(greeting.exists)
        XCTAssertEqual(question.label, questionText, "Should show question at top of view")
        XCTAssertEqual(explanation.label, explanationText, "Should show explanation in view")
        XCTAssertEqual(time.label, timeText, "Should show the correct default time")
    

当我运行测试时,它失败并给我这个消息:

未能获得匹配的快照:从输入 ( StaticText,标识符:'问题',标签:'你想几点起床?', StaticText, identifier: 'Explanation', label: '这应该是每天的同一时间,包括周末和休息日。当我们有规律的作息时,我们最好的睡眠机会就来了。 )

我不确定这是因为 DatePicker() 包含在表单中,还是因为我没有使用正确的 XCUIElementQuery 来查找它?

当我将 DatePicker 移到表单之外时,我可以找到它,但只能使用它的标签,而不是它的可访问性标识符。

可访问性标识符对于 Text 对象工作正常。

我也可以使用

app.datePickers.firstMatch

当它在表单之外时,而不是当它包含在表单中时。

我发现this 的答案描述了当 SwiftUI 对象包含在表单中时的一些奇怪行为,但仍然无法解决我的问题。

非常感谢。

tl:dr 如果 DatePicker 包含在 SwiftUI 表单中,则在 UITesting 时无法让 XCUIElementQuery 返回 DatePicker 元素。

【问题讨论】:

【参考方案1】:

我已经找到了答案,任何有兴趣的人都可以使用。

首先,一个基本的建议,如果您在 XCode 中进行 UI 测试时难以了解如何访问元素,只需使用记录功能并手动访问元素。

这就是我所做的,它向我展示了在 SwiftUI 中点击 DatePicker() 之前,它实际上显示为一个按钮,因此在上面的示例中我使用了以下代码来访问它:

let alarmTimeButton = app.tables.buttons["Time"]

【讨论】:

以上是关于使用 XCUIElementQuery 在 SwiftUI 中查找嵌入在表单中的 DatePicker() 的可访问性(标识符:)的主要内容,如果未能解决你的问题,请参考以下文章

如何在 XCUIElementQuery 中获取 XCUIElement 的索引?

如何将expectationForPredicate 与XCUIElementQuery UISwitch 一起使用

UITest XCUIElementQuery 缺少元素

XCUIElementQuery 将匹配自定义类的所有实例

Xcode 7 UI 测试 XCUIElementQuery 随机未正确更新

使用 SWI 序言