引言:为什么 Docker 和 Swift 是集成测试的理想组合?
现代 iOS 和 macOS 开发不仅需要单元测试,还需要完整的集成测试。当您的应用程序与数据库、外部 API 或文件系统交互时,单独测试每个组件已不再足够。这正是 Docker 发挥作用的地方。
Docker 允许为测试创建相同的环境,消除了“在我机器上能运行”的问题。对于 Swift 开发者来说,这一点尤为重要:容器化使得测试服务器端 Swift 应用程序(Vapor、Kitura)以及模拟 iOS 应用程序的基础设施(数据库、缓存、消息队列)成为可能。
在本文中,我们将介绍使用 Docker 进行 Swift 集成测试的完整配置流程:从创建测试环境到在 CI/CD 中运行。
1. 环境准备:Docker 和 Swift
1.1. 安装 Docker 和 Swift Toolchain
首先,请确保您已安装以下工具:
- Docker Desktop(适用于 macOS)或 Docker Engine(适用于 Linux)
- Swift Toolchain 5.7 及以上版本(可从 swift.org 下载)
- Xcode 14+(如果测试 iOS 组件)
1.2. 为 Swift 创建 Dockerfile
首先,为我们的 Swift 应用程序创建一个基础 Docker 镜像。在项目根目录下创建 Dockerfile 文件:
# DockerfileFROM swift:5.9-focal AS base
# 设置工作目录WORKDIR /app
# 复制 Package.swift 清单文件COPY Package.swift ./COPY Sources/ ./Sources/COPY Tests/ ./Tests/
# 构建项目RUN swift build -c debug
# 用于测试的最终镜像FROM base AS testCMD ["swift", "test", "--parallel"]此镜像构建项目并运行测试。对于集成测试,我们需要额外的服务。
2. 使用 Docker Compose 进行集成测试
Docker Compose 允许同时运行多个容器。对于典型场景,我们需要:
- 运行 Swift 应用程序的容器
- 运行 PostgreSQL(或其他数据库)的容器
- 运行 Redis(用于缓存)的容器
2.1. docker-compose.yml 示例
# docker-compose.ymlversion: '3.8'
services: postgres: image: postgres:15 environment: POSTGRES_USER: test_user POSTGRES_PASSWORD: test_pass POSTGRES_DB: test_db ports: - "5432:5432" healthcheck: test: ["CMD-SHELL", "pg_isready -U test_user -d test_db"] interval: 5s timeout: 5s retries: 5
redis: image: redis:7-alpine ports: - "6379:6379"
swift-tests: build: context: . dockerfile: Dockerfile.test depends_on: postgres: condition: service_healthy redis: condition: service_started environment: DATABASE_URL: "postgres://test_user:test_pass@postgres:5432/test_db" REDIS_URL: "redis://redis:6379" volumes: - .:/app2.2. 用于测试的专用 Dockerfile
创建 Dockerfile.test,它将等待依赖项就绪:
# Dockerfile.testFROM swift:5.9-focal
WORKDIR /app
# 安装 netcat 用于检查连接RUN apt-get update && apt-get install -y netcat-openbsd && rm -rf /var/lib/apt/lists/*
COPY Package.swift ./RUN swift package resolve
COPY . .
# 等待 PostgreSQL 和 RedisCOPY wait-for-services.sh /usr/local/bin/RUN chmod +x /usr/local/bin/wait-for-services.sh
CMD ["wait-for-services.sh"]wait-for-services.sh 脚本:
#!/bin/bash# wait-for-services.sh
echo "等待 PostgreSQL..."while ! nc -z postgres