QAUP_Management/deploy/docker/integration-test.sh

768 lines
23 KiB
Bash
Executable File

#!/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 <container_name>"
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 "$@"