swiftxctestswift-testing

How to test predicate-based expectation with Swift Testing?


Sometimes, I have to write tests that validate that some value changes eventually. It happens, for example, if I need to deal with unstructured concurrency. Here's an example of such kind of tests in XCTest:

let predicate = NSPredicate { service, _ in
    guard let service = service as? SomeService else {
        return false
    }
    return service.something == expectedValue
}
let expectation = XCTNSPredicateExpectation(predicate: predicate, object: service)

sut.doSomething(expectedValue)

wait(for: [expectation], timeout: 1.0)

How would be possible to write such tests in Testing?


Solution

  • Depending on the structure of your code, you might be able to use a Confirmation. In simple cases, though, what I do is:

    while (somethingHasWrongValue) {
        await Task.yield()
    }
    #expect(somethingHasRightValue)
    

    The last line is, strictly speaking, logically unnecessary, but as a matter of style and clarity I like to pound in that final nail by asserting a direct positive expectation.

    This move is so common in my own testing code that I have embodied it in a macro, so I can actually write:

    await #while(somethingHasWrongValue)
    #expect(somethingHasRightValue)