Tests d'intégration Swift avec Docker : niveau avancé
Les tests d'intégration sont une étape clé du développement d'applications Swift fiables. Contrairement aux tests unitaires, ils vérifient l'interaction entre des composants réels : base de données, services réseau, système de fichiers. Docker permet d'isoler ces dépendances, rendant les tests reproductibles et indépendants de l'environnement du développeur. Dans cet article, nous aborderons les techniques avancées de tests d'intégration pour les applications Swift (iOS et côté serveur) utilisant Docker.
1. Fondamentaux de la conteneurisation Docker pour les tests Swift
Avant d'aborder les scénarios avancés, il est important de comprendre l'architecture de base. Docker permet d'exécuter les dépendances (PostgreSQL, Redis, serveurs mock) dans des conteneurs isolés, qui sont automatiquement lancés avant les tests et détruits après.
Pour le Swift côté serveur (Vapor, Kitura), nous utilisons l'image officielle Swift. Pour les applications iOS, Docker ne peut pas lancer le simulateur, mais il est parfaitement adapté pour tester la couche réseau et le backend.
Exemple de fichier Docker Compose de base pour un projet Vapor :
version: '3.8'services: app: image: swift:5.10-focal working_dir: /app volumes: - .:/app depends_on: - db - redis environment: - DATABASE_URL=postgres://user:pass@db:5432/testdb - REDIS_URL=redis://redis:6379
db: image: postgres:16-alpine environment: POSTGRES_USER: user POSTGRES_PASSWORD: pass POSTGRES_DB: testdb ports: - "5432:5432"
redis: image: redis:7-alpine ports: - "6379:6379"Ce fichier lance trois conteneurs : le serveur Swift lui-même, PostgreSQL et Redis. Écrivons maintenant un test d'intégration qui vérifie la sauvegarde d'un utilisateur dans une base de données réelle.
2. Rédaction de tests d'intégration avec XCTest et Docker
Pour les tests d'intégration du Swift côté serveur, nous utiliserons le framework standard XCTest. Le point clé est que les tests doivent être exécutés à l'intérieur du conteneur qui a accès aux autres conteneurs.
Exemple de test pour une application Vapor :
import XCTest@testable import Appimport Vapor
final class UserIntegrationTests: XCTestCase {
var app: Application!
override func setUp() async throws { app = try await Application.make(.testing) try await configure(app)
// Migration de la base de données avant chaque test try await app.autoMigrate() }
override func tearDown() async throws { try await app.autoRevert() try await app.asyncShutdown() }
func testCreateAndFetchUser() async throws { // Création d'un utilisateur via l'API let userDTO = UserDTO(name: "Alice", email: "alice@test.com") try await app.test(.POST, "/users", beforeRequest: { req in try req.content.encode(userDTO) }, afterResponse: { res in XCTAssertEqual(res.status, .created) let createdUser = try res.content.decode(User.self) XCTAssertEqual(createdUser.name, "Alice") })
// Vérification que l'utilisateur a été sauvegardé dans la base try await app.test(.GET, "/users/\\(aliceID)", afterResponse: { res in XCTAssertEqual(res.status, .ok) let fetchedUser = try res.content.decode(User.self) XCTAssertEqual(fetchedUser.email, "alice@test.com") }) }}Ce test lance l'application, effectue des requêtes HTTP vers le serveur réel à l'intérieur du conteneur et vérifie les réponses. Docker garantit que la base de données et Redis sont propres pour chaque exécution.
3. Serveurs mock et isolation des dépendances externes
Au niveau avancé, il est souvent nécessaire de tester l'interaction avec des API externes (systèmes de paiement, services météo)