0Pricing
Swift Academy · Lesson

Async Tests and Performance Measurement

Testing async functions with async/await and measuring with XCTMeasureOptions.

Async Tests and Performance Measurement is a free Swift Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Swift Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Testing Async Functions

Declare test methods as async throws to use await directly inside test bodies without extra boilerplate.

final class FetcherTests: XCTestCase {
  func testFetchReturnsUser() async throws {
    let user = try await UserService().fetchUser(id: 1)
    XCTAssertEqual(user.name, "Alice")
  }
}

Async setUp and tearDown

Override setUp() async throws to perform async initialization before each test.

override func setUp() async throws {
  try await super.setUp()
  sut = await AsyncService.make()
}

XCTestExpectation for Callback APIs

For APIs that use callbacks instead of async/await, use XCTestExpectation and wait(for:timeout:).

func testCallback() {
  let exp = expectation(description: "data received")
  service.fetchWithCallback { data in
    XCTAssertNotNil(data)
    exp.fulfill()
  }
  wait(for: [exp], timeout: 5.0)
}

Inverting Expectations

An inverted expectation fails if it IS fulfilled — useful for asserting that a callback is NOT called.

let noCall = expectation(description: "should not fire")
noCall.isInverted = true
cancelledTask.onComplete { noCall.fulfill() }
wait(for: [noCall], timeout: 1.0)

XCTMeasure for Performance

measure {} runs its block 10 times and reports average time, standard deviation, and baseline comparison.

func testSortPerformance() {
  let data = Array(0..<10_000).shuffled()
  measure {
    _ = data.sorted()
  }
}

XCTMeasureOptions

Configure the number of iterations and what metric to measure (time, memory, CPU).

func testParsePerformance() {
  let options = XCTMeasureOptions()
  options.iterationCount = 5
  measure(options: options) {
    _ = try? JSONDecoder().decode([Item].self, from: largeJSON)
  }
}

Async Performance Measurement

Use measure(metrics:options:block:) with an async block to measure async operations.

func testAsyncFetchPerformance() {
  measure {
    let exp = expectation(description: "done")
    Task {
      _ = try? await service.fetchAll()
      exp.fulfill()
    }
    wait(for: [exp], timeout: 10)
  }
}

Baselines

After running a measure test, set a baseline in Xcode. Future runs fail if performance regresses beyond the threshold.

// Xcode: click the grey icon next to the measure test
// → "Set Baseline" to record the current average
// Subsequent runs compare against the baseline

Testing Actor-Isolated Code

Access actor-isolated state from tests using await.

actor Counter { var value = 0; func increment() { value += 1 } }
final class CounterTests: XCTestCase {
  func testIncrement() async {
    let counter = Counter()
    await counter.increment()
    let val = await counter.value
    XCTAssertEqual(val, 1)
  }
}

Swift Testing Framework (Swift 6)

Swift 6 ships a new Testing framework with @Test, #expect, and @Suite as a modern alternative to XCTest.

import Testing

@Suite struct MathTests {
  @Test func addition() {
    #expect(2 + 2 == 4)
  }
}

Combining XCTest and Swift Testing

Both frameworks can coexist in the same test target during migration from XCTest to Swift Testing.

import XCTest
import Testing
// Legacy XCTestCase tests alongside @Test functions
// Both run when the test target is executed

Quick Check

Which XCTest API measures the performance of a code block and compares it to a stored baseline?

Lesson Recap

Mark test methods async throws to use await directly. Use XCTestExpectation for callback APIs. Measure with measure {} and set baselines for regression detection. Test actors with await. Explore Swift Testing's @Test and #expect for modern tests.

Frequently asked questions

Is the “Async Tests and Performance Measurement” lesson free?

Yes — the full text of “Async Tests and Performance Measurement” is free to read here on the web, and the Swift Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Swift Academy course, upgrade to CoddyKit PRO.

What will I learn in “Async Tests and Performance Measurement”?

Testing async functions with async/await and measuring with XCTMeasureOptions. You practise Swift Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Swift Academy?

No prior experience is required. Swift Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Async Tests and Performance Measurement” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Swift Academy lesson?

Yes. Every Swift Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. XCTestCase Setup, Teardown and Test Methods
  2. XCTAssert Family and Throwing Assertions
  3. Protocol-Based Mocking and Dependency Injection
  4. Async Tests and Performance Measurement
← Back to Swift Academy