Einleitung: Warum Docker und Swift das ideale Paar für Integrationstests sind?
\n\nDie moderne Entwicklung für iOS und macOS erfordert nicht nur Unit-Tests, sondern auch umfassende Integrationstests. Wenn Ihre Anwendung mit einer Datenbank, externen APIs oder dem Dateisystem interagiert, reicht das isolierte Testen jeder Komponente nicht mehr aus. Genau hier kommt Docker ins Spiel.
\n\nDocker ermöglicht die Erstellung identischer Umgebungen für Tests und beseitigt das Problem „bei mir funktioniert es“. Für Swift-Entwickler ist dies besonders relevant: Containerisierung ermöglicht das Testen von Server-Swift-Anwendungen (Vapor, Kitura) sowie die Emulation der Infrastruktur für iOS-Anwendungen (Datenbanken, Caches, Nachrichtenwarteschlangen).
\n\nIn diesem Artikel behandeln wir den gesamten Zyklus der Einrichtung von Integrationstests für Swift mit Docker: von der Erstellung der Testumgebung bis zum Start in CI/CD.
\n\n1. Vorbereitung der Umgebung: Docker und Swift
\n\n1.1. Installation von Docker und Swift Toolchain
\n\nStellen Sie zunächst sicher, dass Folgendes installiert ist:
\n- \n
- Docker Desktop (für macOS) oder Docker Engine (für Linux) \n
- Swift Toolchain Version 5.7+ (herunterladbar von swift.org) \n
- Xcode 14+ (wenn Sie iOS-Komponenten testen) \n
1.2. Erstellen eines Dockerfiles für Swift
\n\nBeginnen wir mit der Erstellung eines Basis-Docker-Images für unsere Swift-Anwendung. Erstellen Sie eine Datei Dockerfile im Stammverzeichnis des Projekts:
# Dockerfile\nFROM swift:5.9-focal AS base\n\n# Arbeitsverzeichnis festlegen\nWORKDIR /app\n\n# Manifest-Dateien Package.swift kopieren\nCOPY Package.swift ./\nCOPY Sources/ ./Sources/\nCOPY Tests/ ./Tests/\n\n# Projekt bauen\nRUN swift build -c debug\n\n# Finales Image für Tests\nFROM base AS test\nCMD ["swift", "test", "--parallel"]\n\n\nDieses Image baut das Projekt und führt die Tests aus. Für Integrationstests benötigen wir zusätzliche Dienste.
\n\n2. Integrationstests mit Docker Compose
\n\nDocker Compose ermöglicht das gleichzeitige Ausführen mehrerer Container. Für ein typisches Szenario benötigen wir:
\n- \n
- Einen Container mit unserer Swift-Anwendung \n
- Einen Container mit PostgreSQL (oder einer anderen Datenbank) \n
- Einen Container mit Redis (für Caching) \n
2.1. Beispiel docker-compose.yml
\n\n# docker-compose.yml\nversion: '3.8'\n\nservices:\n postgres:\n image: postgres:15\n environment:\n POSTGRES_USER: test_user\n POSTGRES_PASSWORD: test_pass\n POSTGRES_DB: test_db\n ports:\n - "5432:5432"\n healthcheck:\n test: ["CMD-SHELL", "pg_isready -U test_user -d test_db"]\n interval: 5s\n timeout: 5s\n retries: 5\n\n redis:\n image: redis:7-alpine\n ports:\n - "6379:6379"\n\n swift-tests:\n build:\n context: .\n dockerfile: Dockerfile.test\n depends_on:\n postgres:\n condition: service_healthy\n redis:\n condition: service_started\n environment:\n DATABASE_URL: "postgres://test_user:test_pass@postgres:5432/test_db"\n REDIS_URL: "redis://redis:6379"\n volumes:\n - .:/app\n\n\n2.2. Spezielles Dockerfile für Tests
\n\nErstellen wir ein Dockerfile.test, das auf die Bereitschaft der Abhängigkeiten wartet:
# Dockerfile.test\nFROM swift:5.9-focal\n\nWORKDIR /app\n\n# Netcat für Verbindungsprüfungen installieren\nRUN apt-get update && apt-get install -y netcat-openbsd && rm -rf /var/lib/apt/lists/*\n\nCOPY Package.swift ./\nRUN swift package resolve\n\nCOPY . .\n\n# Auf PostgreSQL und Redis warten\nCOPY wait-for-services.sh /usr/local/bin/\nRUN chmod +x /usr/local/bin/wait-for-services.sh\n\nCMD ["wait-for-services.sh"]\n\n\nSkript wait-for-services.sh:
#!/bin/bash\n# wait-for-services.sh\n\necho "Warte auf PostgreSQL..."\nwhile ! nc -z postgres