Introdução
\nO teste de integração é uma etapa crítica do desenvolvimento que verifica a interação dos componentes da sua aplicação Swift com dependências externas: bancos de dados, APIs, sistemas de arquivos e serviços de rede. No entanto, as abordagens tradicionais para teste de integração no macOS/iOS frequentemente sofrem do "problema de ambiente" — testes que funcionam na máquina do desenvolvedor podem falhar no servidor CI devido a diferenças nas versões de bibliotecas, configurações de rede ou configuração do banco de dados.
\nO Docker resolve esse problema radicalmente: você empacota todas as dependências (PostgreSQL, Redis, servidores Mock) em contêineres isolados que são executados de forma idêntica em qualquer plataforma. Neste artigo, exploraremos técnicas avançadas de teste de integração Swift com Docker: desde a configuração do ambiente de teste até a execução paralela e integração com CI/CD.
\n\n1. Preparação do ambiente de teste com Docker Compose
\nVamos começar criando um ambiente isolado para os testes. Em vez de executar cada serviço manualmente, usamos docker-compose.yml para descrever declarativamente todas as dependências.
Exemplo de docker-compose.yml para projeto Swift
\nversion: '3.8'\nservices:\n postgres_test:\n image: postgres:15-alpine\n environment:\n POSTGRES_USER: test_user\n POSTGRES_PASSWORD: test_pass\n POSTGRES_DB: swift_test_db\n ports:\n - "5433:5432" # Usamos porta não padrão para evitar conflito com o banco local\n tmpfs: /var/lib/postgresql/data # Dados em memória — limpeza rápida\n\n redis_test:\n image: redis:7-alpine\n ports:\n - "6380:6379"\n\n mock_server:\n build: ./mock-server # Servidor Mock personalizado em Vapor\n ports:\n - "8081:8080"\n environment:\n LOG_LEVEL: debug\n\nCódigo Swift para configuração dinâmica de testes
\nPara que os testes se conectem aos contêineres Docker em vez de serviços locais, usamos variáveis de ambiente:
\nimport XCTest\n\nfinal class IntegrationTests: XCTestCase {\n var app: XCTestApplication?\n\n override func setUp() async throws {\n // Obtemos configuração das variáveis de ambiente (definidas no CI ou docker-compose)\n let dbHost = ProcessInfo.processInfo.environment["DB_HOST"] ?? "localhost"\n let dbPort = Int(ProcessInfo.processInfo.environment["DB_PORT"] ?? "5433") ?? 5433\n let redisHost = ProcessInfo.processInfo.environment["REDIS_HOST"] ?? "localhost"\n let mockHost = ProcessInfo.processInfo.environment["MOCK_HOST"] ?? "http://localhost:8081"\n\n // Configuramos a aplicação de teste (ex.: Vapor ou Kitura)\n let config = AppConfig(\n database: DatabaseConfig(host: dbHost, port: dbPort, \n username: "test_user", password: "test_pass",\n database: "swift_test_db"),\n redis: RedisConfig(host: redisHost, port: 6380),\n mockServiceURL: mockHost\n )\n\n app = try await XCTestApplication.start(config: config)\n }\n\n override func tearDown() async throws {\n try await app?.shutdown()\n }\n}\n\n2. Configuração avançada: execução paralela e isolamento de testes
\nUm dos principais problemas dos testes de integração é o tempo de execução. O Docker permite executar várias cópias do ambiente de teste em paralelo, acelerando significativamente a execução.
\n\nEstratégia de isolamento: um contêiner por classe de teste
\nUsamos docker-compose --project-name para criar instâncias únicas:
#!/bin/bash\n# Execução de testes com project-name único para execução paralela\nTEST_SUITE=$1\nPROJECT_NAME="swift_test_${TEST_SUITE}_$(date +%s)"\n\ndocker-compose -p $PROJECT_NAME up -d --force-recreate\nsleep 5 # Aguardamos a inicialização dos contêineres\n\n# Executamos a classe de teste específica\nxcodebuild test -scheme MyApp -destina