Unit Testing with XCTest
Tests prove your code works and keep it working as you change it. You'll write XCTestCase tests, assert with XCTAssertEqual , use setUp / tearDown , test async code, mock with protocols, and meet the new Swift Testing framework.
Learn Unit Testing with XCTest in our free Swift course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick…
Part of the free Swift course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
What You'll Learn in This Lesson
1️⃣ Your First Test
Subclass XCTestCase , write methods that start with test , and assert the result. Xcode finds and runs them automatically.
2️⃣ setUp and tearDown
setUp() runs before each test to build fresh state; tearDown() runs after to clean it up. This keeps every test isolated and repeatable.
Your turn. Fill in the base class, the method prefix, and the assertion.
3️⃣ Async Tests and Mocking
Mark a test method async to await async code directly. Coding to a protocol lets you swap in a fast, offline mock during tests.
Now you try. Fill in the keywords that make a test async-aware.
4️⃣ The New Swift Testing Framework
Apple's newer Swift Testing framework uses the @Test macro and #expect instead of XCTest's class and assertions. It reads more naturally and coexists with XCTest.
📋 Quick Reference
Write a small test class with setUp, an equality test, and a nil test for a divide function.
Practice quiz
Which base class do XCTest test classes inherit from?
- TestCase
- XCTestCase
- UITest
- XCTAssert
Answer: XCTestCase. Test classes subclass XCTestCase in the XCTest framework.
Which assertion checks two values are equal?
- XCTAssertTrue
- XCTAssertNil
- XCTAssertEqual
- XCTFail
Answer: XCTAssertEqual. XCTAssertEqual(a, b) fails the test when a and b differ.
By convention, an XCTest test method name must start with...
- check
- test
- spec
- it
Answer: test. Methods beginning with 'test' are discovered and run automatically.
When does setUp() run?
- Before each test method
- Once for the whole class
- After all tests
- Only on failure
Answer: Before each test method. setUp() runs before every test method to prepare fresh state.
When does tearDown() run?
- Before each test
- Never
- Only once at launch
- After each test method
Answer: After each test method. tearDown() runs after each test to clean up.
How do you test an async function in XCTest?
- You cannot
- Mark the test method async and use await
- Use a Timer
- Use DispatchQueue.main.sync
Answer: Mark the test method async and use await. Modern XCTest lets a test method be async so it can await directly.
Why depend on a protocol to enable mocking?
- It runs faster
- It avoids imports
- You can substitute a fake conforming type in tests
- It removes assertions
Answer: You can substitute a fake conforming type in tests. Coding to a protocol lets you inject a mock implementation during tests.
Which assertion fails when a condition is false?
- XCTAssertTrue
- XCTAssertFalse
- XCTAssertNil
- XCTUnwrap
Answer: XCTAssertTrue. XCTAssertTrue fails if the expression evaluates to false.
What is Apple's newer testing framework that uses #expect and @Test?
- Quick
- Nimble
- SnapshotTesting
- Swift Testing
Answer: Swift Testing. Swift Testing is Apple's modern framework using the @Test macro and #expect.
A good unit test should be...
- Slow and order-dependent
- Fast, isolated, and repeatable
- Reliant on the network
- Random in outcome
Answer: Fast, isolated, and repeatable. Unit tests should be fast, isolated, and deterministic.