本文目录导读:

我来介绍几种快速搭建测试环境的方法,包括脚本方案和最佳实践。
Docker Compose 方案(推荐)
# docker-compose.yml
version: '3.8'
services:
# 数据库
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: testdb
ports:
- "3306:3306"
volumes:
- ./sql/init.sql:/docker-entrypoint-initdb.d/init.sql
redis:
image: redis:6-alpine
ports:
- "6379:6379"
# 消息队列
rabbitmq:
image: rabbitmq:3-management
environment:
RABBITMQ_DEFAULT_USER: admin
RABBITMQ_DEFAULT_PASS: admin123
ports:
- "5672:5672"
- "15672:15672"
# API 服务
app:
build: .
ports:
- "8080:8080"
environment:
DB_HOST: mysql
REDIS_HOST: redis
RABBITMQ_HOST: rabbitmq
depends_on:
- mysql
- redis
- rabbitmq
启动脚本:
#!/bin/bash # setup_test_env.sh echo "🔄 启动测试环境..." docker-compose up -d echo "⏳ 等待服务就绪..." sleep 10 echo "✅ 测试环境就绪!" echo "MySQL: localhost:3306" echo "Redis: localhost:6379" echo "RabbitMQ: localhost:5672" echo "APP: http://localhost:8080"
Python 自动化脚本
# setup_test_env.py
import os
import subprocess
import time
import json
from typing import Dict, List
class TestEnvironmentSetup:
def __init__(self):
self.services = []
self.config_file = "env_config.json"
def load_config(self) -> Dict:
"""加载环境配置文件"""
default_config = {
"services": {
"mysql": {"port": 3306, "version": "8.0"},
"redis": {"port": 6379, "version": "6-alpine"},
"nginx": {"port": 80, "version": "latest"}
},
"app": {
"port": 8080,
"env_vars": {
"ENV": "test",
"DEBUG": "true"
}
}
}
if os.path.exists(self.config_file):
with open(self.config_file, 'r') as f:
return json.load(f)
return default_config
def check_dependencies(self) -> bool:
"""检查必要工具是否安装"""
tools = ['docker', 'docker-compose', 'curl', 'git']
for tool in tools:
try:
subprocess.run([tool, '--version'],
capture_output=True, check=True)
print(f"✅ {tool} 已安装")
except:
print(f"❌ {tool} 未安装")
return False
return True
def setup_database(self) -> bool:
"""设置测试数据库"""
try:
# 启动 MySQL
subprocess.run([
'docker', 'run', '-d',
'--name', 'test-mysql',
'-e', 'MYSQL_ROOT_PASSWORD=test123',
'-e', 'MYSQL_DATABASE=testdb',
'-p', '3306:3306',
'mysql:8.0'
], check=True)
# 等待数据库就绪
time.sleep(10)
# 创建测试数据
test_data = """
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100),
email VARCHAR(100)
);
INSERT INTO users (name, email) VALUES
('Test User', 'test@example.com');
"""
with open('/tmp/init.sql', 'w') as f:
f.write(test_data)
subprocess.run([
'docker', 'exec', '-i', 'test-mysql',
'mysql', '-uroot', '-ptest123', 'testdb',
], input=test_data.encode(), check=True)
print("✅ 数据库设置完成")
return True
except Exception as e:
print(f"❌ 数据库设置失败: {e}")
return False
def setup_mock_services(self):
"""设置模拟服务"""
mocks = {
'payment': {'port': 8081, 'response': {'status': 'success'}},
'notification': {'port': 8082, 'response': {'sent': True}}
}
for name, config in mocks.items():
self.create_mock_server(name, config)
def create_mock_server(self, name: str, config: Dict):
"""创建模拟服务器"""
from flask import Flask, jsonify
import threading
app = Flask(__name__)
@app.route('/api/' + name, methods=['POST', 'GET'])
def mock_endpoint():
return jsonify(config['response'])
def run_mock():
app.run(port=config['port'])
thread = threading.Thread(target=run_mock, daemon=True)
thread.start()
print(f"✅ 模拟服务 {name} 运行在端口 {config['port']}")
def setup_environment_variables(self):
"""设置环境变量"""
env_vars = {
'DB_URL': 'mysql://root:test123@localhost:3306/testdb',
'REDIS_URL': 'redis://localhost:6379',
'LOG_LEVEL': 'DEBUG',
'APP_ENV': 'test'
}
with open('.env', 'w') as f:
for key, value in env_vars.items():
f.write(f"{key}={value}\n")
print("✅ 环境变量已设置")
def run_tests(self):
"""运行测试"""
# 单元测试
subprocess.run(['python', '-m', 'pytest', 'tests/', '-v'])
# 集成测试
subprocess.run(['python', '-m', 'pytest', 'tests/integration/', '-v'])
def cleanup(self):
"""清理测试环境"""
services = ['test-mysql', 'test-redis', 'test-rabbitmq']
for service in services:
try:
subprocess.run(['docker', 'stop', service], capture_output=True)
subprocess.run(['docker', 'rm', service], capture_output=True)
print(f"✅ 清理 {service}")
except:
pass
def setup(self):
"""完整设置流程"""
print("🚀 开始搭建测试环境...")
if not self.check_dependencies():
print("❌ 请先安装必要工具")
return False
config = self.load_config()
# 设置各组件
self.setup_database()
self.setup_mock_services()
self.setup_environment_variables()
print("🎉 测试环境搭建完成!")
return True
# 使用示例
if __name__ == "__main__":
env = TestEnvironmentSetup()
env.setup()
Shell 一键脚本
#!/bin/bash
# quick_test_env.sh
set -e
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
log() {
echo -e "${GREEN}[$(date +'%H:%M:%S')]${NC} $1"
}
error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# 检查 Docker
check_docker() {
if ! command -v docker &> /dev/null; then
error "Docker 未安装"
exit 1
fi
log "Docker 已安装"
}
# 创建测试网络
create_network() {
docker network create test-network 2>/dev/null || true
log "测试网络已创建"
}
# 启动基础设施
start_infrastructure() {
log "启动数据库..."
docker run -d \
--name test-postgres \
--network test-network \
-e POSTGRES_DB=testdb \
-e POSTGRES_USER=test \
-e POSTGRES_PASSWORD=test123 \
-p 5432:5432 \
postgres:13
log "启动缓存..."
docker run -d \
--name test-redis \
--network test-network \
-p 6379:6379 \
redis:6-alpine
log "启动消息队列..."
docker run -d \
--name test-rabbitmq \
--network test-network \
-e RABBITMQ_DEFAULT_USER=test \
-e RABBITMQ_DEFAULT_PASS=test123 \
-p 5672:5672 \
rabbitmq:3-management
}
# 等待服务就绪
wait_for_services() {
log "等待服务就绪..."
sleep 15
# 检查 PostgreSQL
if docker exec test-postgres pg_isready -U test; then
log "PostgreSQL 就绪"
fi
# 检查 Redis
if docker exec test-redis redis-cli ping; then
log "Redis 就绪"
fi
}
# 初始化测试数据
init_test_data() {
log "初始化测试数据..."
# 创建表
docker exec -i test-postgres psql -U test -d testdb << EOF
CREATE TABLE IF NOT EXISTS products (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
price DECIMAL(10,2),
created_at TIMESTAMP DEFAULT NOW()
);
INSERT INTO products (name, price) VALUES
('Test Product 1', 99.99),
('Test Product 2', 199.99),
('Test Product 3', 299.99);
EOF
log "测试数据初始化完成"
}
# 部署测试应用
deploy_test_app() {
log "部署测试应用..."
# 从 GitHub 拉取测试应用
if [ -d "test-app" ]; then
cd test-app && git pull
else
git clone https://github.com/example/test-app.git
cd test-app
fi
# 构建并运行
docker build -t test-app .
docker run -d \
--name test-app \
--network test-network \
-p 8080:8080 \
-e DB_HOST=test-postgres \
-e REDIS_HOST=test-redis \
-e RABBITMQ_HOST=test-rabbitmq \
test-app
}
# 运行健康检查
health_check() {
log "运行健康检查..."
# 检查应用
if curl -s http://localhost:8080/health | grep -q "OK"; then
log "✅ 应用健康检查通过"
else
error "❌ 应用健康检查失败"
fi
# 检查 API
if curl -s http://localhost:8080/api/products | grep -q "products"; then
log "✅ API 响应正常"
else
error "❌ API 响应异常"
fi
}
# 清理环境
cleanup() {
log "清理测试环境..."
docker stop test-app test-postgres test-redis test-rabbitmq 2>/dev/null
docker rm test-app test-postgres test-redis test-rabbitmq 2>/dev/null
docker network rm test-network 2>/dev/null
log "环境已清理"
}
# 主函数
main() {
case "${1:-setup}" in
setup)
check_docker
create_network
start_infrastructure
wait_for_services
init_test_data
deploy_test_app
health_check
log "🎉 测试环境搭建完成!"
echo ""
echo "访问地址:"
echo " API: http://localhost:8080"
echo " PostgreSQL: localhost:5432"
echo " Redis: localhost:6379"
echo " RabbitMQ: http://localhost:15672"
;;
cleanup)
cleanup
;;
restart)
cleanup
main setup
;;
*)
echo "用法: $0 {setup|cleanup|restart}"
exit 1
;;
esac
}
main "$@"
Ansible Playbook(大项目)
# test_env.yml
---
- name: Setup Test Environment
hosts: test-servers
become: yes
vars:
test_db_name: testdb
test_db_user: testuser
test_db_password: testpass123
tasks:
- name: Install Docker
apt:
name: docker.io
state: present
- name: Start Docker service
service:
name: docker
state: started
enabled: yes
- name: Create test directories
file:
path: "/opt/test-env/{{ item }}"
state: directory
mode: '0755'
loop:
- config
- data
- logs
- name: Deploy docker-compose
copy:
content: |
version: '3'
services:
app:
image: "{{ app_image }}"
ports:
- "8080:8080"
environment:
DB_HOST: db
DB_NAME: "{{ test_db_name }}"
depends_on:
- db
volumes:
- ./logs:/app/logs
db:
image: postgres:13
environment:
POSTGRES_DB: "{{ test_db_name }}"
POSTGRES_USER: "{{ test_db_user }}"
POSTGRES_PASSWORD: "{{ test_db_password }}"
volumes:
- ./data:/var/lib/postgresql/data
dest: /opt/test-env/docker-compose.yml
- name: Start services
docker_compose:
project_src: /opt/test-env
state: present
- name: Wait for services
wait_for:
port: "{{ item }}"
delay: 5
timeout: 60
loop:
- 8080
- 5432
- name: Init test data
postgresql_db:
name: "{{ test_db_name }}"
state: present
delegate_to: localhost
快速使用建议
最小化启动脚本
#!/bin/bash # 最简测试环境启动 # 1. 启动数据库 docker run -d --name test-db -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD=root mysql:8.0 # 2. 启动缓存 docker run -d --name test-cache -p 6379:6379 redis:alpine # 3. 等待就绪 sleep 10 && echo "Ready!"
环境检查工具
# env_checker.py
import requests
import sys
def check_environment():
checks = {
"Database": ("mysql://localhost:3306", "3306"),
"Redis": ("redis://localhost:6379", "6379"),
"API": ("http://localhost:8080/health", "8080")
}
all_passed = True
for service, (url, port) in checks.items():
try:
if "http" in url:
r = requests.get(url, timeout=5)
status = "✅" if r.status_code == 200 else "❌"
else:
import socket
s = socket.socket()
s.settimeout(2)
s.connect(('localhost', int(port)))
status = "✅"
s.close()
print(f"{status} {service}: {url}")
except:
print(f"❌ {service}: {url} - 不可访问")
all_passed = False
return all_passed
if __name__ == "__main__":
if not check_environment():
sys.exit(1)
- 使用 Docker Compose:最快捷的方式,适合大多数场景
- 配置模板化:使用环境变量和配置文件
- 健康检查:确保服务真正就绪后再使用
- 数据持久化:测试数据可以重复使用
- 网络隔离:使用 Docker 网络隔离服务
- 日志记录:保留日志便于调试
- 清理机制:提供清理脚本释放资源
选择哪种方案取决于你的具体需求,但 Docker Compose + 脚本的方式通常是最实用的组合。