UI 测试 - isSelected 总是返回 false

Posted

技术标签:

【中文标题】UI 测试 - isSelected 总是返回 false【英文标题】:UI Tests - isSelected is always returning false 【发布时间】:2017-03-21 18:48:46 【问题描述】:

我们最近使用 Xcode 8.2.1 (8C1002) 将 Swift 2.3 项目更新为 Swift 3,现在我们与 tableViews 和 isSelected 属性相关的大部分 UI 测试都不起作用。它总是返回 false,即使选择了对象(我们可以在 ios 模拟器中看到它)。

有没有人遇到过类似的问题?我们的代码在转换之前在 Swift 2.3 中可以正常工作。下面是我们检索 tableView 单元格的方法:

let cell = app.tables.cells.element(at: 4)

注意:app 是一个 XCUIApplication。

下面是我们检查它是否被选中的方法:

XCTAssert(cell.isSelected)

另一个观察结果是,我们确定对象存在是因为 waitForExpectations 正在返回 true:

let existsPredicate = NSPredicate(format: "exists = 1")
expectation(for: existsPredicate, evaluatedWith: cell, handler: nil)
waitForExpectations(timeout: 20, handler: nil)

编辑:为了替换isSelected,我尝试将NSPredicate 与selected = 1isSelected = 1 一起使用。没有工作。我还尝试根据其他问题的答案使用acessibilityValue,但这并不是那么简单,因为有时我的表格视图中的项目是通过编程方式选择/取消选择的。此外,该方法涉及向应用程序添加测试代码,这不是一个好的做法。

悬赏结束后编辑:由于没有人能找到解决该问题的方法,而这显然是 Xcode 中的一个错误,我已向 Apple 提交了一份错误报告。当他们发布带有修复的 Xcode 版本时,我会在这里发表评论。

额外编辑:在我上次编辑后的一天,dzoanb 提供了一个实用的答案。

【问题讨论】:

【参考方案1】:

我做了一些测试和一些研究。您可以查看为此目的创建的应用程序>>here<<。如果您可以检查一下,那就太好了(这需要一些工作)。也有 UI 测试来证明它有效。此外,还有两种选择,一种是 vanilla XCTest,另一种是我与同事 AutoMate 一起创建的有很多助手的库。但这不是重点。

这是我发现的:

1) XCUIElementisSelected 属性依赖于 accessibilityTrait。在 XCTest 中选择的元素必须设置 UIAccessibilityTraitSelected

2) 我无法重现您的问题,但我能够控制 isSelected 属性。

3) 是的,它需要一些代码,但如果它对你很重要,它应该可以与 VoiceOver 一起使用。

所有必要的代码都在您的自定义UITableViewCell 子类中。并使用覆盖 UIAccessibilityElement accessibilityTraits 属性。

private var traits: UIAccessibilityTraits = UIAccessibilityTraitNone

// MARK: UITableViewCell life cycle
override func awakeFromNib() 
    super.awakeFromNib()
    traits = super.accessibilityTraits


// MARK: UIAccessibilityElement
override var accessibilityTraits: UIAccessibilityTraits 
    get 
        if isSelected 
            return traits | UIAccessibilityTraitSelected
        
        return traits
    

    set 
        traits = newValue
    

希望对你有帮助。

【讨论】:

【参考方案2】:

您是否尝试过在点击前后打断点,并检查单元格的值?喜欢这里的 WWDC 视频:https://youtu.be/7zMGf-0OnoU (从 10 分钟开始)

【讨论】:

它对我不起作用。我收到的结果不是“来自调试器的消息:LLDB RPC 服务器已崩溃。崩溃日志位于 ~/Library/Logs/DiagnosticReports 并具有前缀 'lldb-rpc-server'。请提交错误并附上最近的崩溃日志。”。 我用prints代替,点击前后isSelected的值为false,点击后在模拟器中被选中。 我也尝试打印单元格的value,而不是isSelectedprint(cell.value!))。什么都没出来。 您是否尝试过确保 Xcode 将目标视为可命中目标?尝试 XCUIElement 的“isHittable”属性,并尝试使用可访问性检查器检查单元格。您还可以尝试记录测试,看看 Xcode 是否会在升级到 Swift 3.0 后做任何不同的事情? 是的,它是可点击的。刚刚用断言测试了它。如何使用记录功能通过 Xcode 创建断言?单元格按下正在工作,我可以在模拟器中看到它,但仍然 cell.isSelected 返回 false。【参考方案3】:

isSelected 仅适用于继承自 UIControl 的视图。 UIControl.isSelected 通知XCUIElement.isSelected

由于UITableViewCell 不继承自UIControl,因此当您观察cell.isSelected 时,您不会在测试中看到您想要的值。

我建议,如果您希望通过 UI 测试对其进行测试,请向 Apple 提交功能请求以使 UIControl 成为协议,然后您可以扩展您的单元以符合该协议,或者将 UITableViewCell.isSelected 添加到通知XCUIElement.isSelected 的属性。

【讨论】:

另外,UITableViewCell 有自己的 isSelected 属性。 developer.apple.com/reference/uikit/uitableviewcell/…【参考方案4】:

@dzoanb 解决方案可以在不添加私有变量的情况下工作:

override var accessibilityTraits: UIAccessibilityTraits 
    get 
        if isSelected 
            return super.accessibilityTraits | UIAccessibilityTraitSelected
        
        return super.accessibilityTraits
    

    set 
        super.accessibilityTraits = newValue
    

【讨论】:

【参考方案5】:

无法在 Swift 4 下编译该代码。 这对我有用。

public override var accessibilityTraits: UIAccessibilityTraits 
    get 
        if isSelected 
            return super.accessibilityTraits.union(.selected)
        
        return super.accessibilityTraits
    

    set 
        super.accessibilityTraits = newValue
    

【讨论】:

以上是关于UI 测试 - isSelected 总是返回 false的主要内容,如果未能解决你的问题,请参考以下文章

stm32c8t6初始化mpu6050失败,总是返回8问题的解决

stm32c8t6初始化mpu6050失败,总是返回8问题的解决

stm32c8t6初始化mpu6050失败,总是返回8问题的解决

为啥 -[UIKeyInput hasText] 总是为 UITextField 返回 NO?

iOS UI测试中元素lastSnapshot的子属性总是为空,为啥?

isEnable() 和 isDisplayed() 和 isSelected()