Async Setup and Teardown in XCTestCase
How to make setUpWithError() and tearDownWithError() async in XCTestCase for iOS development in Swift

XCTestCase
is kind enough to allow us to simply mark our test functions with async
if we need them to be async. Unfortunately the same is not true for setUpWithError
and tearDownWithError
. Marking either of these async will result in the following build error:
Method does not override any method from its superclass.
Thankfully there is a fairly simple solution to this problem. Simply copy the following code into a new file and subclass XCAsyncTestCase
instead of XCTestCase
.
Also, be sure to override asyncSetUpWithError
and asyncTearDownWithError
rather than the standard setUpWithError
and tearDownWithError
. For an explanation of how this works, continue reading below.
The key to this solution is the wait
function, which accepts an async block of code. This async block is executed inside a new task and uses a semaphore to block execution from continuing until the async block completes. The function will fire off a new async task withTask.init
and signal the semaphore when it completes.
Meanwhile, execution will simply halt on the line semaphore.wait()
until the semaphore has been signaled. We then use this wait
function inside our typical setup and teardown functions, passing calls to our async versions instead and awaiting their completion.