NEW: Nominations are now open for the 2019 Swift Community Awards! >>

How to do conditional test tear down using addTeardownBlock()

Swift version: 5.1

Paul Hudson    @twostraws   

All XCTestCase subclasses have access to setUp() and tearDown() instance methods, plus setUp() and tearDown() class methods for one-time setup and tear down. But sometimes you need to add conditional tear down code: if your test creates a resource that must be destroyed, you can add that as an additional tear down step using the addTeardownBlock() method.

As an example, consider this test method:

func testDatabaseQuery() {
    let database = connectToDatabase()
    let results = database.fetchExampleData()

    XCTAssertEqual(results.count, 1, "We should receive exactly one result.")

That connects to a database, runs an example query, and checks the result. However, behind the scenes our database needs to be reset every time a connection is finished. If all our tests relied on the database being created then we could add the cleanup code either to the tearDown() instance method or to the tearDown() class method, but if it’s only used sometimes then that isn’t an option.

Fortunately, the addTeardownBlock() is designed to fix this: you can pass in any code you want to run when your test is being torn down, and it will be run after the current test finishes, but before the tearDown() instance method.

In the case of the connectToDatabase() method that needs clean up, we could write that clean up code directly into each test, but that just duplicates code and is likely to cause problems. So, instead we’re going to add the clean up right inside the connection code, like this:

func connectToDatabase() -> Database {
    let database = Database()

    addTeardownBlock {

    return database

That database.cleanUp() code will be called only when the surrounding test is complete, so it acts a bit like defer except the scope is the current test.

It’s important to get the order of set up and tear down correct, because various things happen at different times. If you have two tests in your XCTestCase here’s how it would look:

  1. The setUp() class method is called.
  2. The setUp() instance method is called.
  3. One test is run.
  4. Any tear down blocks that were registered are run.
  5. The tearDown() instance method is called.
  6. The setUp() instance method is called again.
  7. The second test is run.
  8. Any tear down blocks that were registered are run.
  9. The tearDown() instance method is called again.
  10. The tearDown() class method is called.

You won’t need to use tear down blocks often, but they are a useful tool to have.

SAVE 20% ON iOS CONF SG The largest iOS conference in Southeast Asia is back in Singapore for the 5th time in January 2020, now with two days of workshops plus two days of talks on SwiftUI, Combine, GraphQL, and more! Save a massive 20% on your tickets by clicking on this link.

Available from iOS

Similar solutions…

About the Swift Knowledge Base

This is part of the Swift Knowledge Base, a free, searchable collection of solutions for common iOS questions.

Buy Testing Swift Buy Practical iOS 12 Buy Pro Swift Buy Swift Design Patterns Buy Swift Coding Challenges Buy Server-Side Swift (Vapor Edition) Buy Server-Side Swift (Kitura Edition) Buy Hacking with macOS Buy Advanced iOS Volume One Buy Advanced iOS Volume Two Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with Swift Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Beyond Code

Was this page useful? Let us know!

Average rating: 5.0/5