Teste de Integração Swift com Docker: Nível Avançado
O teste de integração é uma etapa fundamental no desenvolvimento de aplicações Swift confiáveis. Diferente dos testes unitários, ele verifica a interação entre componentes reais: banco de dados, serviços de rede, sistema de arquivos. O Docker permite isolar essas dependências, tornando os testes reproduzíveis e independentes do ambiente do desenvolvedor. Neste artigo, abordaremos técnicas avançadas de teste de integração para aplicações Swift (iOS e lado do servidor) utilizando Docker.
1. Fundamentos da Containerização Docker para Testes Swift
Antes de nos aprofundarmos em cenários avançados, é importante entender a arquitetura básica. O Docker permite executar dependências (PostgreSQL, Redis, servidores mock) em contêineres isolados, que são automaticamente iniciados antes dos testes e destruídos após.
Para Swift no servidor (Vapor, Kitura), usamos a imagem oficial do Swift. Para aplicações iOS, o Docker não pode executar o simulador, mas é excelente para testar a camada de rede e o backend.
Exemplo de arquivo Docker Compose básico para um projeto 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"Este arquivo inicia três contêineres: o servidor Swift, PostgreSQL e Redis. Agora, vamos escrever um teste de integração que verifica a persistência de um usuário em um banco de dados real.
2. Escrevendo Testes de Integração com XCTest e Docker
Para testes de integração no Swift do servidor, usaremos o framework padrão XCTest. O ponto chave é que os testes devem ser executados dentro do contêiner que tem acesso aos outros contêineres.
Exemplo de teste para uma aplicação 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)
// Migração do banco de dados antes de cada teste try await app.autoMigrate() }
override func tearDown() async throws { try await app.autoRevert() try await app.asyncShutdown() }
func testCreateAndFetchUser() async throws { // Cria um usuário via 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") })
// Verifica se o usuário foi salvo no banco 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") }) }}Este teste inicia a aplicação, executa requisições HTTP para o servidor real dentro do contêiner e verifica as respostas. O Docker garante que o banco de dados e o Redis estejam limpos para cada execução.
3. Servidores Mock e Isolamento de Dependências Externas
Em um nível avançado, é frequentemente necessário testar a interação com APIs externas (sistemas de pagamento, serviços meteorológicos)