如何正确编写用于Swift UI开关的UI测试

7

有人知道如何正确编写一个切换按钮的UI测试吗?即使在一个新项目中,只有一个切换按钮而没有其他任何UI元素,在进行测试时也会出现这种错误:

Failed to get matching snapshot: Multiple matching elements found for <XCUIElementQuery: 0x60000108c410>.
Sparse tree of matches:
→Application, pid: 26580, label: 'TestToggle'
 ↳Window (Main)
  ↳Other
   ↳Other
    ↳Other
     ↳Other
      ↳Switch, label: 'Test switch', value: 1
       ↳Switch, label: 'Test switch', value: 1

UI的外观如下:

struct ContentView: View {
  @State private var toggleValue = true
  var body: some View {
    Toggle("Test switch", isOn: $toggleValue)
      .padding()
  }
}

测试看起来像这样(这两行都给我同样的错误):

     func testExample() throws {
        let app = XCUIApplication()
        app.launch()
        
        XCTAssertTrue(app.switches["Test switch"].value as? String == "1")
//        XCTAssertTrue(app.switches["Test switch"].isEnabled)
    }

我一定是做错了什么。如果只有一个,怎么会出现两个开关?我看到的在线文章似乎没有提到这一点。感谢任何帮助。谢谢 :)
2个回答

9

我在一些 Slack 频道中得到了几个回复,结果发现对于某些原因,使用“Toggle”时我不能依赖默认标签进行测试(与“Text”和“Button”不同),需要创建自定义的辅助功能标识符。

因此,只需添加类似如下内容:

    Toggle("Test switch", isOn: $toggleValue)
        .padding()
        .accessibilityIdentifier("testSwitch")

然后像这样测试是否有效:

func testExample() throws {
    let app = XCUIApplication()
    app.launch()
    XCTAssertTrue(app.switches["testSwitch"].isEnabled)
    XCTAssertTrue(app.switches["testSwitch"].value as? String == "1")
}

2
我不确定你的测试是否断言了你想要测试的内容。isEnabled 返回“元素是否启用用户交互”。如果用户可以与之交互,则 isEnabled 返回 true,即使切换关闭。 - Ruben Veldman
1
是的,你说得对,我想测试它是否已经打开。谢谢 :) 然而,那不是我面临的问题。问题在于accessibilityIdentifier。我已更新答案将两者都包括进去。 - Michael Vescovo
很奇怪,你不能依赖所提供的标签。 - acmpo6ou

1
我不确定您为什么会收到错误信息,但您可以尝试向切换按钮添加accessibilityIdentifier并通过该方式查找。
例如:
struct ContentView: View {
  @State private var toggleValue = true
  var body: some View {
    Toggle("Test switch", isOn: $toggleValue)
      .padding()
      .accessibilityIdentifier("testSwitch")
  }
}

在你的测试中,你可以使用以下代码查找元素:

func testExample() throws {
        let app = XCUIApplication()
        app.launch()
        
        XCTAssertTrue(app.switches["testSwitch"].value as? String == "1")
    }

顺便提一下,如果你想测试 Toggle 开关是否开启或关闭,不应该使用 isEnabled。这将检查“元素是否启用用户交互”。

你应该使用

app.switches["testSwitch"].value as? String == "1" // on

或者

app.switches["testSwitch"].value as? String == "0" // off

根据您想要测试的内容而定。


1
我已经在3.5个月前提供了使用accessibilityIdentifier的答案,正如您可以在上面看到的那样。不确定为什么您要再次发布相同的答案。 - Michael Vescovo
@MichaelVescovo 您的回答使用了 isEnabled,我不确定那是否是您想要测试的内容。我认为您想要测试开关是打开还是关闭。 - Ruben Veldman
它没有起作用的原因是因为我没有添加“accessibilityIdentifier”。这个问题之前已经有人回答过了,而且在你的回答中也提到了。如果你的回答不需要使用“accessibilityIdentifier”,那当然会很有帮助,但事实并非如此。 - Michael Vescovo
1
@MichaelVescovo 我明白了,我可能应该省略 accessibilityIdentifier 部分。老实说,我没有注意到你的答案已经包含了那部分。我想指出的是,在你的测试中使用了 .isEnabled.isEnabled 部分将始终返回 true,除非你指定了 .disabled(true)。我不确定你是否意识到了这一点,因为你可能在测试错误的东西。 - Ruben Veldman
1
我有机会测试这个。是的,你是正确的;我想测试它是否启用和打开。谢谢你的提示!我提出问题的目的是为了解决accessibilityIdentifier的问题,但你发现了我的测试中的一个错误。谢谢 :) 我已经更新了答案,包括两个问题。 - Michael Vescovo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接