XCTest
01 / 02

XCTest: Mocking, UI Tests & CI

XCTest: Mocking, UI Tests & CI

Dependency Injection for Testability

protocol NetworkClient {
    func fetchUser(id: Int, completion: @escaping (User?) -> Void)
}

// Receives its dependency via the initializer -- a test can substitute
// a mock, unlike a class that creates URLSession.shared internally
class UserService {
    let client: NetworkClient
    init(client: NetworkClient) { self.client = client }
}

class MockNetworkClient: NetworkClient {
    var stubbedUser: User?
    func fetchUser(id: Int, completion: @escaping (User?) -> Void) {
        completion(stubbedUser)
    }
}

func testUserServiceReturnsFetchedUser() {
    let mockClient = MockNetworkClient()
    mockClient.stubbedUser = User(id: 1, name: "Alice")
    let sut = UserService(client: mockClient)
    // ... exercise sut and assert, with no real network call made
}

UI Tests (XCUITest)

class LoginUITests: XCTestCase {
    func testLoginFlow() {
        let app = XCUIApplication()
        app.launch()

        // Actually launches the app and taps a real, rendered button --
        // verifies the full integration, not just isolated logic
        app.textFields["Username"].tap()
        app.textFields["Username"].typeText("alice")
        app.buttons["Login"].tap()

        XCTAssertTrue(app.staticTexts["Welcome, alice"].exists)
    }
}

Performance Testing

func testSortPerformance() {
    let largeArray = (0..<10_000).shuffled()

    // Runs multiple times, tracking metrics like wall-clock time --
    // Xcode flags a later code change that makes this meaningfully slower
    measure {
        _ = largeArray.sorted()
    }
}

Running Tests in CI

xcodebuild test \
  -scheme MyApp \
  -destination 'platform=iOS Simulator,name=iPhone 15'

# Runs the same XCTest suite headlessly -- what makes automated CI
# testing (GitHub Actions, Bitrise, Xcode Cloud) possible for
# iOS/macOS projects, without the Xcode GUI open

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free