XCTest: TestCase, Assertions & Async
XCTest is Apple's native testing framework for Swift and Objective-C, integrated directly into Xcode. Tests run from the IDE (Cmd+U), with results shown inline in the editor and the Test Navigator -- no third-party test runner setup required.
Writing a Test Case
import XCTest
@testable import MyApp
class CalculatorTests: XCTestCase {
var sut: Calculator!
// Re-creates fresh state before EACH test method
override func setUp() {
sut = Calculator()
}
override func tearDown() {
sut = nil
}
func testAddition() {
// Arrange-Act-Assert
let result = sut.add(2, 3)
XCTAssertEqual(result, 5)
}
func testDivisionByZeroThrows() {
XCTAssertThrowsError(try sut.divide(10, by: 0)) { error in
XCTAssertEqual(error as? CalculatorError, .divisionByZero)
}
}
}Common Assertions
XCTAssertEqual(a, b) / XCTAssertNotEqual(a, b) -- value equality with a descriptive failure message.
XCTAssertTrue(x) / XCTAssertFalse(x) -- Boolean checks.
XCTAssertNil(x) / XCTAssertNotNil(x) -- more concise and standardized than a manual if + XCTFail.
XCTAssertThrowsError / XCTAssertNoThrow -- verifies a throwing function's error behavior.
XCTUnwrap(optional) -- safely unwraps, failing the TEST (not crashing the process) if nil, unlike force-unwrapping with !.
Testing Async Code with XCTestExpectation
func testFetchUserSucceeds() {
let expectation = XCTestExpectation(description: "fetch completes")
networkClient.fetchUser(id: 1) { user in
XCTAssertEqual(user?.name, "Alice")
expectation.fulfill()
}
// Pauses the test until fulfill() is called, or fails on timeout
wait(for: [expectation], timeout: 5)
}Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free