Writing good unit tests with XCTest

Testing Junior Swift 5.0+ iOS 17+ Reviewed By Alok Singh

Spot the bug

These tests pass alone but fail when run together. Tap the cause.

  1. final class CartTests: XCTestCase {
  2. static let cart = Cart()
  3. func testAddItem() {
  4. Self.cart.add(.apple)
  5. XCTAssertEqual(Self.cart.count, 1)
  6. }
  7. func testRemoveItem() {
  8. Self.cart.add(.apple)
  9. Self.cart.remove(.apple)
  10. XCTAssertEqual(Self.cart.count, 0)
  11. }
  12. }
Hint 1 of 1

What carries over from one test to the next?

Choose an answer, then open Show answer below to check it.

Show answer
  • Answer: line 2 static let cart = Cart()

Line 2 shares one cart across tests, so results depend on order. Create a new Cart in each test or in setUp.

30-second answer

Subclass XCTestCase and write test… methods that arrange inputs, act once and assert the outcome with XCTAssert functions. Create fresh objects per test in setUp or inside the test so tests are independent and can run in any order or in parallel. Inject dependencies so tests are fast, deterministic and offline.

Practise saying it · 30 s. No recording, just a timer

Explain how you write unit tests.

Say your answer out loud, then check which of these points you covered:

  • Arrange, act, assert
  • Independent tests
  • Injected dependencies

Deep dive

Name tests by behaviour: test_total_includesTax.

Use XCTUnwrap instead of force-unwrapping.

addTeardownBlock cleans up per test.

Measure coverage, but judge tests by the bugs they would catch.

Common mistakes

  • Shared mutable state between tests.
  • Several unrelated behaviours in one test.

Senior take & follow-ups

Seniors write isolated, behaviour-named tests with injected dependencies.

Follow-up questions

Think of your answer first, then open the hint.

  1. Why must tests be independent?

    Show hint

    Order and parallel execution vary.

  2. XCTUnwrap vs force unwrap?

    Show hint

    XCTUnwrap fails the test instead of crashing the run.

Suggest a fix if something here is wrong or out of date.