Tests en Swift : unit, integration, e2e de A à Z

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Introduction : Pourquoi les tests sont le fondement d'une application Swift fiable

Le développement pour iOS et macOS nécessite non seulement une belle interface, mais aussi une logique stable. Les tests en Swift ne sont pas une option, mais une nécessité. Sans tests, même un petit changement peut casser une fonctionnalité qui fonctionnait depuis des années. Dans cet article, nous allons aborder trois niveaux de test : unit (tests unitaires), integration (tests d'intégration) et e2e (tests de bout en bout). Vous apprendrez à les configurer, les écrire et les exécuter correctement sur les plateformes Apple. À la fin, des conseils pratiques pour organiser l'architecture des tests.

Niveau 1 : Tests unitaires — les bases fondamentales

Les tests unitaires vérifient des fonctions, méthodes ou classes individuelles de manière isolée. En Swift, le framework principal est XCTest. Il est intégré à Xcode, ne nécessite pas de dépendances tierces et est parfait pour tester la logique métier.

Comment écrire votre premier test unitaire

Créez une nouvelle cible de test unitaire dans Xcode (File → New → Target → Unit Testing Bundle). Ajoutez ensuite une classe de test :

import XCTest
@testable import MyApp

final class CalculatorTests: XCTestCase {
    
    var sut: Calculator!
    
    override func setUpWithError() throws {
        sut = Calculator()
    }
    
    override func tearDownWithError() throws {
        sut = nil
    }
    
    func testAddition() {
        // Given
        let a = 5
        let b = 3
        
        // When
        let result = sut.add(a, b)
        
        // Then
        XCTAssertEqual(result, 8, "L'addition doit être correcte")
    }
}

Bonnes pratiques des tests unitaires

  • Isolation : chaque test ne teste qu'une seule unité de code. Utilisez setUp et tearDown pour réinitialiser l'état.
  • Nommage : utilisez le modèle test[Méthode]_[Condition]_[RésultatAttendu].
  • Mocks et stubs : pour les dépendances externes (réseau, base de données), utilisez des protocoles et remplacez-les dans les tests.
  • Couverture : visez 70-80% de couverture de code, mais ne cherchez pas les 100% — testez les chemins critiques.

Exemple avec un mock

protocol NetworkServiceProtocol {
    func fetchData(completion: @escaping (Result<Data, Error>) -> Void)
}

class MockNetworkService: NetworkServiceProtocol {
    var shouldReturnError = false
    
    func fetchData(completion: @escaping (Result<Data, Error>) -> Void) {
        if shouldReturnError {
            completion(.failure(NSError(domain: "test", code: 1)))
        } else {
            completion(.success(Data()))
        }
    }
}

func testFetchDataSuccess() {
    let mock = MockNetworkService()
    let viewModel = ViewModel(networkService: mock)
    
    mock.shouldReturnError = false
    viewModel.loadData()
    XCTAssertTrue(viewModel.isDataLoaded)
}

Niveau 2 : Tests d'intégration — vérification des interactions

Les tests d'intégration vérifient comment différents modules du système fonctionnent ensemble : base de données + réseau, UI + logique métier, plusieurs services. En Swift, on utilise XCTest avec des dépendances réelles (ou in-memory).

Scénario typique : Core Data + Network

import XCTest
@testable import MyApp

class UserServiceIntegrationTests: XCTestCase {
    
    var coreDataStack: CoreDataStack!
    var networkService: NetworkService!
    var userService: UserService!
    
    override func setUp() {
        coreDataStack = CoreDataStack(inMemory: true) // in-memory pour les tests
        networkService = NetworkService()
        userService = UserService(coreDataStack: coreDataStack, networkService: networkService)
    }
    
    func testSaveUserFromNetwork() {
        // Créer une attente pour la requête asynchrone
        let expectation = self.expe                

Blogs

Book Recommendations