Skip to content
Learni
View all tutorials
Tests & Qualité

How to Create Unit Tests with XCTest in 2026

12 minBEGINNER
Lire en français

Introduction

XCTest is Apple's official framework for unit and UI testing on iOS, macOS, and tvOS. It lets you verify that your code behaves as expected before launching the app. In this tutorial, we will create a test target, write simple assertions, and run tests directly inside Xcode. Mastering XCTest from the beginning improves code quality and reduces regressions during updates.

Prerequisites

  • Xcode 16 or later
  • Basic knowledge of Swift
  • An existing iOS project (or a new empty project)

Add a Test Target

Xcode Project
// In Xcode: File > New > Target...
// Choose iOS Unit Testing Bundle
// Name: MyAppTests
// Language: Swift

Creating a separate test target isolates test code from production code and enables Xcode's built-in code coverage tools.

Create the Test Class

MyAppTests.swift
import XCTest
@testable import MyApp

final class MyAppTests: XCTestCase {
    override func setUpWithError() throws {
        // Code executed before each test
    }

    override func tearDownWithError() throws {
        // Code executed after each test
    }
}

The class inherits from XCTestCase. setUp and tearDown ensure a clean environment for every test.

Write a Simple First Test

MyAppTests.swift
func testAddition() throws {
    let result = 2 + 2
    XCTAssertEqual(result, 4, "Addition should return 4")
}

XCTAssertEqual is the most common assertion. The error message only appears when the test fails.

Test a Real Function

Calculator.swift
// Source file
struct Calculator {
    func multiply(_ a: Int, _ b: Int) -> Int {
        return a * b
    }
}

We test a real function from the main project by importing the module with @testable.

Add the Test for the Function

MyAppTests.swift
func testMultiply() throws {
    let calc = Calculator()
    let result = calc.multiply(3, 4)
    XCTAssertEqual(result, 12)
}

Every method starting with test is automatically executed by Xcode.

Best Practices

  • Name your tests descriptively (testFunctionName_Scenario_ExpectedResult)
  • Test only one behavior per method
  • Use @testable import to access internal types
  • Run tests on every commit via Xcode or the command line

Common Mistakes to Avoid

  • Forgetting to import the module with @testable
  • Using hard-coded values without clear setup
  • Not testing edge cases (0, nil, negative values)
  • Leaving tests that depend on execution order

Going Further

Discover our complete courses on iOS and Swift testing: https://learni-group.com/formations