2

我正在尝试编写单元测试,我希望我的测试用例等待某个类中的变量发生变化。所以我用一个谓词创建一个期望,并等待值改变 using XCTWaiter().wait(for: [expectation], timeout: 2.0),我认为这是正确的使用方法。

以下代码按预期工作:

class ExpectationTests: XCTestCase {
var x: Int = 0

private func start() {
    _ = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false) { _ in
        self.x = 1
    }
}

func test1() {
    let predicate = NSPredicate(format: "x == 1")
    let expectation = XCTNSPredicateExpectation(predicate: predicate, object: self)
    start()
    let result = XCTWaiter().wait(for: [expectation], timeout: 2.0)
    switch result {
    case .completed:    XCTAssertEqual(x, 1)
    case .timedOut:     XCTFail()
    default:            XCTFail()
    }
}

变量 (x) 由 start() 函数设置为 0,然后在 0.5 秒后变为 1。谓词等待该 var (x) 更改。这有效:result设置为.completed并且 var 实际上设置为 1。是的:-)

但是,当我要观察的变量不是本地变量,而是在某个类中时,它就不再起作用了。考虑以下代码片段:

class MyClass: NSObject {
    var y: Int = 0
    
    func start() {
        _ = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false) { _ in
            self.y = 1
        }
    }
}

func test2() {
    let myClass = MyClass()
    let predicate = NSPredicate(format: "y == 1")
    let expectation = XCTNSPredicateExpectation(predicate: predicate, object: myClass)
    myClass.start()
    let result = XCTWaiter().wait(for: [expectation], timeout: 2.0)
    switch result {
    case .completed:    XCTAssertEqual(myClass.y, 1)
    case .timedOut:     XCTFail()
    default:            XCTFail()
    }
}

它与第一段代码非常相似,但它总是在 2 秒后以 beresult结束.timedOut。我看不出我做错了什么。我使用myClass传递给期望的对象中的变量,而不是本地变量和对象'self'。(当测试结束时,类 varmyClass.y实际上设置为 1。)

我尝试用 替换XCTNSPredicateExpectation(predicate:object)expectation(for:evaluatedWith:handler)但这没有任何区别。

StackOverflow 上的许多示例都使用检查existsin的谓词XCUIElement。但我不是在测试 UI;我只想检查某个类中的某个 var 是否在超时时间内发生了变化。我不明白为什么这与检查 var existsin如此不同XCUIElement

有任何想法吗?!先感谢您!

4

1 回答 1

0

好吧,感谢@Willeke 为我指明了正确的方向,我确实找到了解决方案,但我不能说我完全理解它......这是我的代码现在的样子:

// MARK: - Test 2
    class MyClass: NSObject {
        var y: Int = 0
        
        func start() {
            _ = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false) { _ in
                self.y = 1
            }
        }
    }
    
    func test2() {
        let myClass = MyClass()
        let predicate = NSPredicate() { any, _ in
//            guard let myClass = any as? MyClass else { return false }
            return myClass.y == 1
        }
        let expectation = XCTNSPredicateExpectation(predicate: predicate, object: myClass)
        myClass.start()
        let result = XCTWaiter().wait(for: [expectation], timeout: 2.0)
        switch result {
        case .completed:    XCTAssertEqual(myClass.y, 1)
        case .timedOut:     XCTFail()
        default:            XCTFail()
        }
    }

我可以使用带有闭包的谓词,该闭包定期检查 var 是否已更改,如果它具有正确的值则返回 true。(它大约每秒执行一次。)但是,XCTWaiter考虑到文档中的描述expectation(for:evaluatedWith:handler:)(这是 的一种方便方法XCTNSPredicateExpectation),我实际上认为这就是目的:

期望定期评估谓词。当谓词评估为真时,测试满足预期。

所以,我很高兴我可以继续前进,但我仍然不明白为什么这不起作用,NSPredicate(format: "y == 1")而不是带有闭包的谓词......

于 2020-10-14T15:55:36.367 回答