Studies on Reactive Patterns with Swift Concurrency

This question has come up before e.g. here. The short answer is that, no, we don't plan to implement this exact shape of API in Swift Testing.

The somewhat longer answer is that most problems for which XCTestExpectation/XCTWaiter are a solution can be solved directly with Swift Concurrency. In the case of your example here, the solution is probably to just use await:

@Test func `async operation`() async {
  await someAsyncFunction()
}

Of course, you indicate that you want to make sure that someAsyncFunction() returns in a reasonable amount of time, and you've set a 10-second timer on your waiter. When you use XCTest, one test runs at a time in the current process, meaning that the kernel's scheduler and the Swift runtime's task scheduler aren't juggling your test alongside others. Swift Testing uses in-process parallelization instead which is much faster, but means that the schedulers do not guarantee that your test's task will get 10 seconds of execution time (or any other non-zero amount of execution time) before your 10 second timer fires[1].

All that said… we are experimenting with similar API that would cover cases like "check if this condition has been met after n seconds" that are hard to model with Swift Concurrency, but our experiments likely require changes in the Swift runtime to implement correctly. My colleague on the Testing Workgroup, @maartene, is working on a pitch in this area (that I won't spoil for him) that would eventually allow us to implement API of this approximate shape.


  1. We don't recommend fine-grained timeouts for your tests even when using XCTest, for what it's worth. Strictly speaking, you don't have any time guarantees with XCTest either, and you may find that while a 10 second timeout is sufficient on your M5 MacBook Pro, your colleague's 15-year-old Pentium 4 Linux system takes 30 seconds and your CI system takes 2 minutes. ↩︎

7 Likes