Xcode UI 测试发现多个按钮

Posted

技术标签:

【中文标题】Xcode UI 测试发现多个按钮【英文标题】:Xcode UI Tests Multiple Buttons Found 【发布时间】:2017-05-30 01:34:22 【问题描述】:

我的 UI 测试显示使用以下代码时发现多个按钮时遇到问题。

app.buttons["Upgrade"].tap()

所以我重新运行了我的单元测试并在运行该行之前设置了一个断点,然后点击了记录按钮并单击了该按钮,它生成了以下代码。

app.children(matching: .window).element(boundBy: 0).children(matching: .other).element(boundBy: 1).buttons["Upgrade"].tap()

当然,在测试的顶部我有let app = XCUIApplication()

知道为什么会这样吗?

有时在调试器中运行 p UIApplication.shared.windows 时,它在数组中有 2 个值。我不知道为什么,因为我从来没有多个窗口。我与 windows 的唯一交互是有时将UIApplication.shared.keyWindow?.rootViewController 设置为不同的视图控制器,以及didFinishLaunchingWithOptions 中的以下代码。

// Get view controllers ready
self.window = UIWindow(frame: UIScreen.main.bounds)
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let mainViewController: ViewController = mainStoryboard.instantiateViewController(withIdentifier: "FirstView") as! ViewController
// Show view controller
self.window?.rootViewController = mainViewController
self.window?.makeKeyAndVisible()

在 if 语句和 else 语句中我有几乎相同的代码,除了 FirstViewSecondView

【问题讨论】:

打印app.buttons["Upgrade"].debugDescription 可能会提供提示... 我想我以前遇到过这个问题。您可以尝试在您正在测试的按钮上抛出一个唯一的可访问性标识符并重新记录测试。 @PauloMattos 我设置了一个断点并试图打印它,但它打印了很多东西。我快速浏览了一下,找不到任何有用的东西或我不知道的东西。 @Adrian 现在试试这个 @Adrian 使用唯一可访问性标识符重新录制测试时也是如此。除了 .buttons["Upgrade"] 之外,它将“升级”切换为我设置的唯一标识符。 【参考方案1】:

出现此消息是因为屏幕上有多个按钮,accessibilityIdentifieraccessibilityLabel value、“升级”,因此无法确定是哪一个点按。

使用录制版本时它起作用的原因是录制工具已经确定需要缩小搜索范围以在索引1处的.other类型的元素内进行搜索,以确保与哪个“升级”按钮进行交互。

这不是您的窗口的问题,而是您的按钮标识符的唯一性,以及您在测试中如何处理它们。

如果按钮仅在相关应用的页面上使用一次,最好在UIButton 上设置唯一的accessibilityIdentifier。它的值在您的应用程序的该页面中应该是唯一的,因此请确保您没有在其他任何地方使用相同的字符串。然后您可以明确地访问该按钮:

// app code
let upgradeButton: UIButton!
upgradeButton.accessibilityIdentifier = "upgradeButton"

// test code
let app = XCUIApplication()
let upgradeButton = app.buttons["upgradeButton"]
upgradeButton.tap()

在屏幕上同时出现多个同一个升级按钮的情况下(例如,按钮是屏幕上重复图案的一部分,比如有很多产品在售),没关系让他们每个人都拥有相同的accessibilityIdentifier,但您应该更改您在测试中访问元素的方式,使用element(boundBy:) 来访问指定索引处的项目:

// app code
let upgradeButton: UIButton!
upgradeButton.accessibilityIdentifier = "upgradeButton"

// test code
let app = XCUIApplication()
let upgradeButton = app.buttons["upgradeButton"].element(boundBy: 1) // second upgrade button
upgradeButton.tap()

在这种情况下,您也可以采取找到正确的容器视图,并在其中搜索升级按钮的方法。

// test code
let app = XCUIApplication()
let upgradeButtonContainer = app.descendants(matching: .any).containing(.button, identifier: "upgradeButton").element(boundBy: 1) // second upgrade button-containing element
let upgradeButton = upgradeButtonContainer.buttons["upgradeButton"]
upgradeButton.tap()

【讨论】:

这根本没有意义。我确信在当前视图控制器上我只有 1 个按钮,其值为 Upgrade。我还发现这只发生在 iPhone 4S 上。【参考方案2】:

我遇到了同样的问题并尝试了多种方法来摆脱它。最终,当我将 Xcode 更新到 8.3.3 并将模拟器操作系统更新到 ios 10.3 时,我发现问题开始发生。 将我的模拟器操作系统切换回 iOS 10.2,它运行良好。

【讨论】:

【参考方案3】:

自从更新到 Xcode 8.3 后,我看到了类似的问题,其中 XCUIElementQuery 在应该只有一个结果时返回多个结果。此版本中可能引入了一个错误。

https://forums.developer.apple.com/thread/75546 描述了这个错误,雷达在这里: https://openradar.appspot.com/31498932

我尝试了发布的解决方法,尝试强制我的查询以 XCUIElementQuery 的形式返回所需的对象,然后使用 element(boundBy:),它对我有用。

UI 测试的不稳定程度令人不安。

【讨论】:

以上是关于Xcode UI 测试发现多个按钮的主要内容,如果未能解决你的问题,请参考以下文章

Xcode 7 中的特定 UI 测试

UI 测试失败:发现多个匹配错误

当存在多个测试类时,Xcode iOS UI 测试使用 SIGABRT 崩溃

使用多个 ViewController、Xcode 将代码连接到情节提要中的 UI

我可以并行运行多个 iOS UI 测试吗?

Xcode 8:UI 测试远程按钮错误:找不到焦点元素