#!/bin/bash # QAUP 集成测试脚本 set -e SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" TEST_LOG="$PROJECT_ROOT/logs/integration_test_$(date +%Y%m%d_%H%M%S).log" # 颜色输出 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' print_message() { local color=$1 local message=$2 echo -e "${color}${message}${NC}" echo "$(date '+%Y-%m-%d %H:%M:%S') $message" >> "$TEST_LOG" } # 测试结果统计 TOTAL_TESTS=0 PASSED_TESTS=0 FAILED_TESTS=0 FAILED_TEST_NAMES=() # 记录测试结果 record_test_result() { local test_name=$1 local result=$2 TOTAL_TESTS=$((TOTAL_TESTS + 1)) if [ "$result" = "PASS" ]; then PASSED_TESTS=$((PASSED_TESTS + 1)) print_message $GREEN "✓ $test_name: PASS" else FAILED_TESTS=$((FAILED_TESTS + 1)) FAILED_TEST_NAMES+=("$test_name") print_message $RED "✗ $test_name: FAIL" fi } # 等待服务就绪 wait_for_service() { local service_name=$1 local url=$2 local max_attempts=${3:-30} local attempt=0 print_message $BLUE "等待 $service_name 服务就绪..." while [ $attempt -lt $max_attempts ]; do if curl -f -s "$url" &>/dev/null; then print_message $GREEN "$service_name 服务已就绪" return 0 fi sleep 2 attempt=$((attempt + 1)) if [ $((attempt % 10)) -eq 0 ]; then print_message $YELLOW "$service_name 等待中... ($attempt/$max_attempts)" fi done print_message $RED "$service_name 服务启动超时" return 1 } # 测试 Docker 环境 test_docker_environment() { print_message $BLUE "测试 Docker 环境..." # 测试 Docker 是否运行 if docker info &>/dev/null; then record_test_result "Docker服务运行" "PASS" else record_test_result "Docker服务运行" "FAIL" return 1 fi # 测试 Docker Compose 是否可用 if docker-compose --version &>/dev/null; then record_test_result "Docker Compose可用" "PASS" else record_test_result "Docker Compose可用" "FAIL" return 1 fi # 测试网络连接 if docker network ls | grep -q qaup; then record_test_result "Docker网络存在" "PASS" else record_test_result "Docker网络存在" "FAIL" fi return 0 } # 测试容器启动 test_container_startup() { print_message $BLUE "测试容器启动..." local containers=("qaup-postgres" "qaup-redis" "qaup-app" "qaup-nginx") for container in "${containers[@]}"; do if docker ps --format "{{.Names}}" | grep -q "^${container}$"; then record_test_result "${container}容器运行" "PASS" else record_test_result "${container}容器运行" "FAIL" fi done } # 测试服务健康检查 test_service_health() { print_message $BLUE "测试服务健康检查..." # 测试数据库健康检查 if docker exec qaup-postgres pg_isready -h localhost -p 5432 -U postgres &>/dev/null; then record_test_result "PostgreSQL健康检查" "PASS" else record_test_result "PostgreSQL健康检查" "FAIL" fi # 测试 Redis 健康检查 if docker exec qaup-redis redis-cli ping | grep -q "PONG"; then record_test_result "Redis健康检查" "PASS" else record_test_result "Redis健康检查" "FAIL" fi # 测试应用健康检查 if wait_for_service "QAUP应用" "http://localhost:8080/actuator/health" 30; then record_test_result "应用健康检查" "PASS" else record_test_result "应用健康检查" "FAIL" fi # 测试 Nginx 健康检查 if wait_for_service "Nginx" "http://localhost/health" 10; then record_test_result "Nginx健康检查" "PASS" else record_test_result "Nginx健康检查" "FAIL" fi } # 测试网络连通性 test_network_connectivity() { print_message $BLUE "测试网络连通性..." # 测试应用到数据库的连接 if docker exec qaup-app nc -z qaup-postgres 5432 &>/dev/null; then record_test_result "应用到数据库连接" "PASS" else record_test_result "应用到数据库连接" "FAIL" fi # 测试应用到 Redis 的连接 if docker exec qaup-app nc -z qaup-redis 6379 &>/dev/null; then record_test_result "应用到Redis连接" "PASS" else record_test_result "应用到Redis连接" "FAIL" fi # 测试 Nginx 到应用的连接 if docker exec qaup-nginx nc -z qaup-app 8080 &>/dev/null; then record_test_result "Nginx到应用连接" "PASS" else record_test_result "Nginx到应用连接" "FAIL" fi } # 测试数据库功能 test_database_functionality() { print_message $BLUE "测试数据库功能..." # 测试数据库连接 if docker exec qaup-postgres psql -U postgres -d qaup -c "SELECT 1;" &>/dev/null; then record_test_result "数据库连接测试" "PASS" else record_test_result "数据库连接测试" "FAIL" return 1 fi # 测试 PostGIS 扩展 if docker exec qaup-postgres psql -U postgres -d qaup -c "SELECT PostGIS_Version();" &>/dev/null; then record_test_result "PostGIS扩展测试" "PASS" else record_test_result "PostGIS扩展测试" "FAIL" fi # 测试表结构 local table_count=$(docker exec qaup-postgres psql -U postgres -d qaup -t -c "SELECT count(*) FROM information_schema.tables WHERE table_schema = 'public';" | xargs) if [ "$table_count" -gt 0 ]; then record_test_result "数据库表结构测试" "PASS" print_message $BLUE "数据库包含 $table_count 个表" else record_test_result "数据库表结构测试" "FAIL" fi # 测试数据库写入 local test_table="integration_test_$(date +%s)" if docker exec qaup-postgres psql -U postgres -d qaup -c "CREATE TABLE $test_table (id SERIAL PRIMARY KEY, test_data TEXT); INSERT INTO $test_table (test_data) VALUES ('test'); DROP TABLE $test_table;" &>/dev/null; then record_test_result "数据库写入测试" "PASS" else record_test_result "数据库写入测试" "FAIL" fi } # 测试 Redis 功能 test_redis_functionality() { print_message $BLUE "测试 Redis 功能..." # 测试 Redis 基本操作 if docker exec qaup-redis redis-cli set test_key "test_value" | grep -q "OK"; then record_test_result "Redis写入测试" "PASS" else record_test_result "Redis写入测试" "FAIL" return 1 fi # 测试 Redis 读取 if docker exec qaup-redis redis-cli get test_key | grep -q "test_value"; then record_test_result "Redis读取测试" "PASS" else record_test_result "Redis读取测试" "FAIL" fi # 清理测试数据 docker exec qaup-redis redis-cli del test_key &>/dev/null # 测试 Redis 内存使用 local memory_usage=$(docker exec qaup-redis redis-cli info memory | grep "used_memory_human" | cut -d: -f2 | tr -d '\r') if [ -n "$memory_usage" ]; then record_test_result "Redis内存信息测试" "PASS" print_message $BLUE "Redis 内存使用: $memory_usage" else record_test_result "Redis内存信息测试" "FAIL" fi } # 测试应用 API test_application_api() { print_message $BLUE "测试应用 API..." # 测试健康检查端点 local health_response=$(curl -s http://localhost:8080/actuator/health) if echo "$health_response" | grep -q '"status":"UP"'; then record_test_result "应用健康端点测试" "PASS" else record_test_result "应用健康端点测试" "FAIL" fi # 测试应用信息端点 if curl -f -s http://localhost:8080/actuator/info &>/dev/null; then record_test_result "应用信息端点测试" "PASS" else record_test_result "应用信息端点测试" "FAIL" fi # 测试应用指标端点 if curl -f -s http://localhost:8080/actuator/metrics &>/dev/null; then record_test_result "应用指标端点测试" "PASS" else record_test_result "应用指标端点测试" "FAIL" fi # 测试应用响应时间 local response_time=$(curl -o /dev/null -s -w '%{time_total}' http://localhost:8080/actuator/health) if (( $(echo "$response_time < 5.0" | bc -l) )); then record_test_result "应用响应时间测试" "PASS" print_message $BLUE "应用响应时间: ${response_time}s" else record_test_result "应用响应时间测试" "FAIL" print_message $YELLOW "应用响应时间较慢: ${response_time}s" fi } # 测试前端访问 test_frontend_access() { print_message $BLUE "测试前端访问..." # 测试 Nginx 健康检查 if curl -f -s http://localhost/health | grep -q "healthy"; then record_test_result "前端健康检查测试" "PASS" else record_test_result "前端健康检查测试" "FAIL" fi # 测试前端页面访问 local http_status=$(curl -o /dev/null -s -w '%{http_code}' http://localhost/) if [ "$http_status" = "200" ]; then record_test_result "前端页面访问测试" "PASS" else record_test_result "前端页面访问测试" "FAIL" print_message $YELLOW "HTTP状态码: $http_status" fi # 测试 API 代理 local api_status=$(curl -o /dev/null -s -w '%{http_code}' http://localhost/prod-api/actuator/health) if [ "$api_status" = "200" ]; then record_test_result "API代理测试" "PASS" else record_test_result "API代理测试" "FAIL" print_message $YELLOW "API代理状态码: $api_status" fi # 测试静态资源 if curl -f -s http://localhost/favicon.ico &>/dev/null; then record_test_result "静态资源访问测试" "PASS" else record_test_result "静态资源访问测试" "FAIL" fi } # 测试数据持久化 test_data_persistence() { print_message $BLUE "测试数据持久化..." # 测试数据库数据持久化 local test_data="persistence_test_$(date +%s)" # 创建测试数据 if docker exec qaup-postgres psql -U postgres -d qaup -c "CREATE TABLE IF NOT EXISTS test_persistence (id SERIAL PRIMARY KEY, data TEXT); INSERT INTO test_persistence (data) VALUES ('$test_data');" &>/dev/null; then record_test_result "数据库数据创建测试" "PASS" else record_test_result "数据库数据创建测试" "FAIL" return 1 fi # 重启数据库容器 print_message $BLUE "重启数据库容器测试持久化..." docker restart qaup-postgres &>/dev/null # 等待数据库重新启动 sleep 10 # 验证数据是否仍然存在 if docker exec qaup-postgres psql -U postgres -d qaup -t -c "SELECT data FROM test_persistence WHERE data = '$test_data';" | grep -q "$test_data"; then record_test_result "数据库持久化测试" "PASS" else record_test_result "数据库持久化测试" "FAIL" fi # 清理测试数据 docker exec qaup-postgres psql -U postgres -d qaup -c "DELETE FROM test_persistence WHERE data = '$test_data';" &>/dev/null # 测试 Redis 持久化 docker exec qaup-redis redis-cli set persistence_test "$test_data" &>/dev/null docker restart qaup-redis &>/dev/null sleep 5 if docker exec qaup-redis redis-cli get persistence_test | grep -q "$test_data"; then record_test_result "Redis持久化测试" "PASS" else record_test_result "Redis持久化测试" "FAIL" fi # 清理 Redis 测试数据 docker exec qaup-redis redis-cli del persistence_test &>/dev/null } # 测试文件上传功能 test_file_upload() { print_message $BLUE "测试文件上传功能..." # 创建测试文件 local test_file="/tmp/test_upload_$(date +%s).txt" echo "This is a test file for upload functionality" > "$test_file" # 检查上传目录是否存在 if [ -d "$PROJECT_ROOT/data/uploads" ]; then # 模拟文件上传(复制到上传目录) cp "$test_file" "$PROJECT_ROOT/data/uploads/" if [ -f "$PROJECT_ROOT/data/uploads/$(basename "$test_file")" ]; then record_test_result "文件上传测试" "PASS" # 清理测试文件 rm -f "$PROJECT_ROOT/data/uploads/$(basename "$test_file")" else record_test_result "文件上传测试" "FAIL" fi else record_test_result "文件上传目录检查" "FAIL" fi # 清理临时文件 rm -f "$test_file" } # 测试日志功能 test_logging() { print_message $BLUE "测试日志功能..." # 检查应用日志 if docker logs qaup-app --tail 10 | grep -q "Started"; then record_test_result "应用日志测试" "PASS" else record_test_result "应用日志测试" "FAIL" fi # 检查 Nginx 访问日志 if docker logs qaup-nginx --tail 10 &>/dev/null; then record_test_result "Nginx日志测试" "PASS" else record_test_result "Nginx日志测试" "FAIL" fi # 检查日志目录 if [ -d "$PROJECT_ROOT/logs" ]; then record_test_result "日志目录检查" "PASS" else record_test_result "日志目录检查" "FAIL" fi } # 测试监控功能 test_monitoring() { print_message $BLUE "测试监控功能..." # 测试监控脚本 if [ -x "$PROJECT_ROOT/docker/monitor.sh" ]; then if "$PROJECT_ROOT/docker/monitor.sh" status &>/dev/null; then record_test_result "监控脚本测试" "PASS" else record_test_result "监控脚本测试" "FAIL" fi else record_test_result "监控脚本存在性检查" "FAIL" fi # 测试告警功能 if [ -x "$PROJECT_ROOT/docker/alert-manager.sh" ]; then if "$PROJECT_ROOT/docker/alert-manager.sh" check &>/dev/null; then record_test_result "告警功能测试" "PASS" else record_test_result "告警功能测试" "FAIL" fi else record_test_result "告警脚本存在性检查" "FAIL" fi } # 测试备份功能 test_backup_functionality() { print_message $BLUE "测试备份功能..." # 测试数据库备份 if [ -x "$PROJECT_ROOT/docker/backup-restore.sh" ]; then if "$PROJECT_ROOT/docker/backup-restore.sh" database &>/dev/null; then record_test_result "数据库备份测试" "PASS" else record_test_result "数据库备份测试" "FAIL" fi else record_test_result "备份脚本存在性检查" "FAIL" fi # 检查备份目录 if [ -d "$PROJECT_ROOT/backup" ]; then record_test_result "备份目录检查" "PASS" else record_test_result "备份目录检查" "FAIL" fi } # 性能测试 test_performance() { print_message $BLUE "测试系统性能..." # 测试并发请求 local concurrent_requests=10 local total_requests=100 print_message $BLUE "执行并发性能测试 ($concurrent_requests 并发, $total_requests 请求)..." # 使用 curl 进行简单的并发测试 local start_time=$(date +%s.%N) for ((i=1; i<=concurrent_requests; i++)); do { for ((j=1; j<=10; j++)); do curl -s http://localhost/health &>/dev/null done } & done wait local end_time=$(date +%s.%N) local duration=$(echo "$end_time - $start_time" | bc) local rps=$(echo "scale=2; $total_requests / $duration" | bc) print_message $BLUE "性能测试结果: ${rps} 请求/秒" # 判断性能是否合格(简单阈值) if (( $(echo "$rps > 50" | bc -l) )); then record_test_result "并发性能测试" "PASS" else record_test_result "并发性能测试" "FAIL" fi # 测试内存使用 local memory_usage=$(docker stats --no-stream --format "{{.MemPerc}}" qaup-app | sed 's/%//') if (( $(echo "$memory_usage < 80" | bc -l) )); then record_test_result "内存使用测试" "PASS" print_message $BLUE "应用内存使用: ${memory_usage}%" else record_test_result "内存使用测试" "FAIL" print_message $YELLOW "应用内存使用较高: ${memory_usage}%" fi } # 安全测试 test_security() { print_message $BLUE "测试安全配置..." # 测试端口访问限制 local restricted_ports=("5432" "6379" "8080") for port in "${restricted_ports[@]}"; do if ! nc -z localhost "$port" 2>/dev/null; then record_test_result "端口${port}访问限制测试" "PASS" else record_test_result "端口${port}访问限制测试" "FAIL" fi done # 测试 HTTP 安全头 local security_headers=("X-Frame-Options" "X-Content-Type-Options" "X-XSS-Protection") for header in "${security_headers[@]}"; do if curl -I -s http://localhost/ | grep -q "$header"; then record_test_result "${header}安全头测试" "PASS" else record_test_result "${header}安全头测试" "FAIL" fi done } # 运行完整集成测试 run_full_integration_test() { print_message $GREEN "=========================================" print_message $GREEN "开始 QAUP 系统集成测试" print_message $GREEN "=========================================" # 确保日志目录存在 mkdir -p "$(dirname "$TEST_LOG")" # 记录测试开始时间 local start_time=$(date +%s) # 执行各项测试 test_docker_environment test_container_startup test_service_health test_network_connectivity test_database_functionality test_redis_functionality test_application_api test_frontend_access test_data_persistence test_file_upload test_logging test_monitoring test_backup_functionality test_performance test_security # 计算测试时间 local end_time=$(date +%s) local duration=$((end_time - start_time)) # 生成测试报告 generate_test_report "$duration" } # 生成测试报告 generate_test_report() { local duration=$1 print_message $GREEN "=========================================" print_message $GREEN "集成测试完成" print_message $GREEN "=========================================" echo "" print_message $BLUE "测试统计:" echo " 总测试数: $TOTAL_TESTS" echo " 通过测试: $PASSED_TESTS" echo " 失败测试: $FAILED_TESTS" echo " 成功率: $(echo "scale=2; $PASSED_TESTS * 100 / $TOTAL_TESTS" | bc)%" echo " 测试时间: ${duration}秒" echo "" if [ $FAILED_TESTS -eq 0 ]; then print_message $GREEN "🎉 所有测试通过!系统部署成功!" echo "" print_message $BLUE "系统已准备就绪,可以投入使用:" echo " 前端访问: http://localhost" echo " API 文档: http://localhost/prod-api/swagger-ui.html" echo " 监控面板: ./docker/monitor.sh watch" echo "" else print_message $RED "❌ 部分测试失败,需要检查以下问题:" echo "" for failed_test in "${FAILED_TEST_NAMES[@]}"; do echo " - $failed_test" done echo "" print_message $YELLOW "建议操作:" echo " 1. 查看详细日志: $TEST_LOG" echo " 2. 检查服务状态: ./docker/monitor.sh status" echo " 3. 查看容器日志: docker logs " echo " 4. 修复问题后重新运行测试" echo "" fi # 创建 JSON 格式的测试报告 local report_file="$PROJECT_ROOT/logs/integration_test_report_$(date +%Y%m%d_%H%M%S).json" cat > "$report_file" << EOF { "test_run": { "timestamp": "$(date -u '+%Y-%m-%dT%H:%M:%S.%3NZ')", "duration_seconds": $duration, "total_tests": $TOTAL_TESTS, "passed_tests": $PASSED_TESTS, "failed_tests": $FAILED_TESTS, "success_rate": $(echo "scale=4; $PASSED_TESTS / $TOTAL_TESTS" | bc), "status": "$([ $FAILED_TESTS -eq 0 ] && echo "SUCCESS" || echo "FAILURE")" }, "failed_tests": [ $(IFS=','; printf ' "%s"' "${FAILED_TEST_NAMES[*]}" | sed 's/","/",\n "/g') ], "log_file": "$TEST_LOG", "report_file": "$report_file" } EOF print_message $BLUE "详细测试报告已生成:" echo " 日志文件: $TEST_LOG" echo " JSON报告: $report_file" # 返回测试结果 return $FAILED_TESTS } # 快速健康检查 quick_health_check() { print_message $BLUE "执行快速健康检查..." test_container_startup test_service_health test_frontend_access if [ $FAILED_TESTS -eq 0 ]; then print_message $GREEN "✓ 快速健康检查通过" return 0 else print_message $RED "✗ 快速健康检查失败" return 1 fi } # 显示帮助信息 show_help() { echo "QAUP 集成测试脚本" echo "" echo "用法: $0 [命令]" echo "" echo "命令:" echo " full 运行完整集成测试" echo " quick 快速健康检查" echo " docker 测试 Docker 环境" echo " containers 测试容器状态" echo " health 测试服务健康状态" echo " network 测试网络连通性" echo " database 测试数据库功能" echo " redis 测试 Redis 功能" echo " api 测试应用 API" echo " frontend 测试前端访问" echo " performance 性能测试" echo " security 安全测试" echo "" echo "示例:" echo " $0 full # 运行完整集成测试" echo " $0 quick # 快速健康检查" echo " $0 performance # 仅运行性能测试" } # 主函数 main() { if [ $# -eq 0 ]; then show_help exit 0 fi local command=$1 case $command in full) run_full_integration_test ;; quick) quick_health_check ;; docker) test_docker_environment generate_test_report 0 ;; containers) test_container_startup generate_test_report 0 ;; health) test_service_health generate_test_report 0 ;; network) test_network_connectivity generate_test_report 0 ;; database) test_database_functionality generate_test_report 0 ;; redis) test_redis_functionality generate_test_report 0 ;; api) test_application_api generate_test_report 0 ;; frontend) test_frontend_access generate_test_report 0 ;; performance) test_performance generate_test_report 0 ;; security) test_security generate_test_report 0 ;; help|--help|-h) show_help ;; *) print_message $RED "未知命令: $command" show_help exit 1 ;; esac # 返回失败测试数量作为退出码 exit $FAILED_TESTS } main "$@"