I've been experiencing some failures in tests and I've worked out they appear to be caused by XCTest expectation waits suspending the Task
instances. Even when they're on a background thread.
Here's a made up test that's a vastly simplified version of the code in my app (please excuse the prints, that's just me mucking around trying to see the sequencing):
func testTask() async throws {
let exp = expectation(description: "")
print("Queuing")
Task.detached(priority: .background) {
let duration = try await ContinuousClock().measure {
print(" Initialing task sleep")
try await Task.sleep(for:.seconds(1))
}
print(" Fulfilling after \(duration)")
exp.fulfill()
}
print("Waiting")
wait(for: [exp], timeout: 4.0)
print("Finished")
}
Now when I run this test the task executes on a background thread and suspends as expected, however it stays suspended for at least 4 seconds and doesn't fulfil until after the expectation has timed out.
Everything I've read so far suggests that you should be able to use expectations with Tasks but so far it's not worked for me.
Am I missing something, or will I have to write some await code to act like an expectation instead?
Notes: This test is a vastly simplified version of a situation in my app. So whilst it may make no sense as a standalone test, it's an accurate representation of what I'm testing. There is also the notion of a traditional completion in it because the real code triggers background tasks which then notify other code of when they finish.
If you can remove the
async
from the test declaration, then this works wherewait(for:)
doesn't:It's also possible to
await
the expectations in anasync
test:I have no explanation for why this works, and
wait(for: [exp], timeout: 4.0)
does not.