如何用脚本快速搭建测试环境

wen 实用脚本 1

本文目录导读:

如何用脚本快速搭建测试环境

  1. Docker Compose 方案(推荐)
  2. Python 自动化脚本
  3. Shell 一键脚本
  4. Ansible Playbook(大项目)
  5. 快速使用建议

我来介绍几种快速搭建测试环境的方法,包括脚本方案和最佳实践。

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)
  1. 使用 Docker Compose:最快捷的方式,适合大多数场景
  2. 配置模板化:使用环境变量和配置文件
  3. 健康检查:确保服务真正就绪后再使用
  4. 数据持久化:测试数据可以重复使用
  5. 网络隔离:使用 Docker 网络隔离服务
  6. 日志记录:保留日志便于调试
  7. 清理机制:提供清理脚本释放资源

选择哪种方案取决于你的具体需求,但 Docker Compose + 脚本的方式通常是最实用的组合。

抱歉,评论功能暂时关闭!