引言
\n集成测试是开发中至关重要的阶段,它检验 Swift 应用各组件与外部依赖(数据库、API、文件系统和网络服务)之间的交互。然而,macOS/iOS 上传统的集成测试方法常常面临"环境问题"——在开发者机器上通过的测试,可能因库版本、网络设置或数据库配置的差异而在 CI 服务器上失败。
\nDocker 从根本上解决了这一问题:您可以将所有依赖(PostgreSQL、Redis、模拟服务器)打包到隔离的容器中,这些容器在任何平台上都能以相同方式运行。本文将介绍 Swift 与 Docker 集成测试的高级技术:从测试环境配置到并行执行以及与 CI/CD 的集成。
\n\n1. 使用 Docker Compose 准备测试环境
\n首先,为测试创建隔离环境。我们不再手动启动每个服务,而是使用 docker-compose.yml 声明式地描述所有依赖。
Swift 项目的 docker-compose.yml 示例
\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" # 使用非标准端口,避免与本地数据库冲突\n tmpfs: /var/lib/postgresql/data # 数据存储在内存中——快速清理\n\n redis_test:\n image: redis:7-alpine\n ports:\n - "6380:6379"\n\n mock_server:\n build: ./mock-server # 基于 Vapor 的自定义模拟服务器\n ports:\n - "8081:8080"\n environment:\n LOG_LEVEL: debug\n\n用于动态配置测试的 Swift 代码
\n为了让测试连接到 Docker 容器而非本地服务,我们使用环境变量:
\nimport XCTest\n\nfinal class IntegrationTests: XCTestCase {\n var app: XCTestApplication?\n\n override func setUp() async throws {\n // 从环境变量获取配置(在 CI 或 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 // 配置测试应用(例如 Vapor 或 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. 高级配置:并行执行与测试隔离
\n集成测试的主要问题之一是其执行时间。Docker 允许并行运行多个测试环境副本,从而显著加快测试运行速度。
\n\n隔离策略:每个测试类一个容器
\n使用 docker-compose --project-name 创建唯一实例:
#!/bin/bash\n# 使用唯一的 project-name 并行运行测试\nTEST_SUITE=$1\nPROJECT_NAME="swift_test_${TEST_SUITE}_$(date +%s)"\n\ndocker-compose -p $PROJECT_NAME up -d --force-recreate\nsleep 5 # 等待容器初始化\n\n# 运行特定测试类\nxcodebuild test -scheme MyApp -destina