UI 测试 - isSelected 总是返回 false

UI Tests - isSelected is always returning false

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

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

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

注意: app 是一个 XCUI 应用程序。

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

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 一起使用。 None 成功了。我还尝试根据其他问题的答案使用 acessibilityValue,但这并不是那么简单,因为有时我的 table 视图中的项目是 selected/unselected 编程的。此外,该方法涉及向应用程序添加测试代码,这不是一个好的做法。

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

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

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

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

由于 UITableViewCell 没有继承自 UIControl,当您观察 cell.isSelected.

时,您在测试中看不到想要的值

我建议,如果你想通过 UI 测试来测试它,你可以向 Apple 提交功能请求以制定 UIControl 协议,然后你可以扩展你的单元格以符合,或将 UITableViewCell.isSelected 添加到通知 XCUIElement.isSelected.

的属性

我做了一些测试和一些研究。您可以查看为此目的创建的应用 >>here<<. It would be great if you could check it out (it required a little bit of work). There are also UI tests to prove it works. Also, two options are available, one is vanilla XCTest and one library with a lot of helpers I'm creating with my colleagues AutoMate。但这不是重点。

这是我发现的:

1) isSelected 属性 of XCUIElement 取决于 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
    }
}

希望对您有所帮助。

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

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

    set {
        super.accessibilityTraits = newValue
    }
}

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

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

    set {
        super.accessibilityTraits = newValue
    }
}