start_test_environment.sh 8.18 KB
#!/bin/bash

# 启动测试环境脚本
# 用于在commit前自动化测试时启动必要的依赖服务

set -e

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 配置
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
TEST_LOG_DIR="$PROJECT_ROOT/test_logs"
PID_FILE="$PROJECT_ROOT/test_environment.pid"

# 日志文件
LOG_FILE="$TEST_LOG_DIR/test_environment.log"
ES_LOG_FILE="$TEST_LOG_DIR/elasticsearch.log"
API_LOG_FILE="$TEST_LOG_DIR/api_test.log"

echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}启动测试环境${NC}"
echo -e "${GREEN}========================================${NC}"

# 创建日志目录
mkdir -p "$TEST_LOG_DIR"

# 检查是否已经运行
if [ -f "$PID_FILE" ]; then
    OLD_PID=$(cat "$PID_FILE")
    if ps -p $OLD_PID > /dev/null 2>&1; then
        echo -e "${YELLOW}测试环境已在运行 (PID: $OLD_PID)${NC}"
        echo -e "${BLUE}如需重启,请先运行: ./scripts/stop_test_environment.sh${NC}"
        exit 0
    else
        rm -f "$PID_FILE"
    fi
fi

# 激活conda环境
echo -e "${BLUE}激活conda环境...${NC}"
source /home/tw/miniconda3/etc/profile.d/conda.sh
conda activate searchengine

# 设置环境变量
echo -e "${BLUE}设置测试环境变量...${NC}"
export PYTHONPATH="$PROJECT_ROOT:$PYTHONPATH"
export TESTING_MODE=true
export LOG_LEVEL=DEBUG

# Elasticsearch配置
export ES_HOST="http://localhost:9200"
export ES_USERNAME="elastic"
export ES_PASSWORD="changeme"

# API配置
export API_HOST="127.0.0.1"
export API_PORT="6003"  # 使用不同的端口避免冲突
export CUSTOMER_ID="test_customer"

# 测试配置
export TEST_TIMEOUT=60
export TEST_RETRY_COUNT=3

echo -e "${BLUE}环境配置:${NC}"
echo "  ES_HOST: $ES_HOST"
echo "  API_HOST: $API_HOST:$API_PORT"
echo "  CUSTOMER_ID: $CUSTOMER_ID"
echo "  LOG_LEVEL: $LOG_LEVEL"
echo "  TESTING_MODE: $TESTING_MODE"

# 检查Elasticsearch是否运行
echo -e "${BLUE}检查Elasticsearch状态...${NC}"
if curl -s "$ES_HOST/_cluster/health" > /dev/null; then
    echo -e "${GREEN}✓ Elasticsearch正在运行${NC}"
else
    echo -e "${YELLOW}⚠ Elasticsearch未运行,尝试启动...${NC}"

    # 尝试启动Elasticsearch(如果安装了本地版本)
    if command -v elasticsearch &> /dev/null; then
        echo -e "${BLUE}启动本地Elasticsearch...${NC}"
        elasticsearch -d -p "$TEST_LOG_DIR/es.pid"
        sleep 10

        # 再次检查
        if curl -s "$ES_HOST/_cluster/health" > /dev/null; then
            echo -e "${GREEN}✓ Elasticsearch启动成功${NC}"
        else
            echo -e "${RED}✗ Elasticsearch启动失败${NC}"
            echo -e "${YELLOW}请手动启动Elasticsearch或配置远程ES地址${NC}"
            exit 1
        fi
    else
        echo -e "${RED}✗ 未找到本地Elasticsearch${NC}"
        echo -e "${YELLOW}请启动Elasticsearch服务或修改ES_HOST配置${NC}"
        exit 1
    fi
fi

# 等待Elasticsearch就绪
echo -e "${BLUE}等待Elasticsearch就绪...${NC}"
for i in {1..30}; do
    if curl -s "$ES_HOST/_cluster/health?wait_for_status=yellow&timeout=1s" | grep -q '"status":"green\|yellow"'; then
        echo -e "${GREEN}✓ Elasticsearch已就绪${NC}"
        break
    fi
    if [ $i -eq 30 ]; then
        echo -e "${RED}✗ Elasticsearch就绪超时${NC}"
        exit 1
    fi
    sleep 1
done

# 创建测试索引(如果需要)
echo -e "${BLUE}准备测试数据索引...${NC}"
curl -X PUT "$ES_HOST/test_products" -H 'Content-Type: application/json' -d'
{
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 0,
    "analysis": {
      "analyzer": {
        "ansj": {
          "type": "custom",
          "tokenizer": "keyword"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "name": {
        "type": "text",
        "analyzer": "ansj"
      },
      "brand_name": {
        "type": "text",
        "analyzer": "ansj"
      },
      "tags": {
        "type": "text",
        "analyzer": "ansj"
      },
      "price": {
        "type": "double"
      },
      "category_id": {
        "type": "integer"
      },
      "spu_id": {
        "type": "keyword"
      },
      "text_embedding": {
        "type": "dense_vector",
        "dims": 1024
      }
    }
  }
}' > /dev/null 2>&1 || echo -e "${YELLOW}索引可能已存在${NC}"

# 插入测试数据
echo -e "${BLUE}插入测试数据...${NC}"
curl -X POST "$ES_HOST/test_products/_bulk" -H 'Content-Type: application/json' -d'
{"index": {"_id": "1"}}
{"name": "红色连衣裙", "brand_name": "测试品牌", "tags": ["红色", "连衣裙", "女装"], "price": 299.0, "category_id": 1, "spu_id": "dress_001"}
{"index": {"_id": "2"}}
{"name": "蓝色连衣裙", "brand_name": "测试品牌", "tags": ["蓝色", "连衣裙", "女装"], "price": 399.0, "category_id": 1, "spu_id": "dress_002"}
{"index": {"_id": "3"}}
{"name": "智能手机", "brand_name": "科技品牌", "tags": ["智能", "手机", "数码"], "price": 2999.0, "category_id": 2, "spu_id": "phone_001"}
{"index": {"_id": "4"}}
{"name": "笔记本电脑", "brand_name": "科技品牌", "tags": ["笔记本", "电脑", "办公"], "price": 5999.0, "category_id": 3, "spu_id": "laptop_001"}
' > /dev/null 2>&1 || echo -e "${YELLOW}测试数据可能已存在${NC}"

# 启动测试API服务
echo -e "${BLUE}启动测试API服务...${NC}"
cd "$PROJECT_ROOT"

# 使用后台模式启动API
python -m api.app \
    --host $API_HOST \
    --port $API_PORT \
    --customer $CUSTOMER_ID \
    --es-host $ES_HOST \
    > "$API_LOG_FILE" 2>&1 &

API_PID=$!
echo $API_PID > "$PID_FILE"

# 等待API服务启动
echo -e "${BLUE}等待API服务启动...${NC}"
for i in {1..30}; do
    if curl -s "http://$API_HOST:$API_PORT/health" > /dev/null; then
        echo -e "${GREEN}✓ API服务已就绪 (PID: $API_PID)${NC}"
        break
    fi
    if [ $i -eq 30 ]; then
        echo -e "${RED}✗ API服务启动超时${NC}"
        kill $API_PID 2>/dev/null || true
        rm -f "$PID_FILE"
        exit 1
    fi
    sleep 1
done

# 验证测试环境
echo -e "${BLUE}验证测试环境...${NC}"

# 测试Elasticsearch连接
if curl -s "$ES_HOST/_cluster/health" | grep -q '"status":"green\|yellow"'; then
    echo -e "${GREEN}✓ Elasticsearch连接正常${NC}"
else
    echo -e "${RED}✗ Elasticsearch连接失败${NC}"
    exit 1
fi

# 测试API健康检查
if curl -s "http://$API_HOST:$API_PORT/health" | grep -q '"status"'; then
    echo -e "${GREEN}✓ API服务健康检查通过${NC}"
else
    echo -e "${RED}✗ API服务健康检查失败${NC}"
    exit 1
fi

# 测试基本搜索功能
if curl -s "http://$API_HOST:$API_PORT/search?q=红色连衣裙" | grep -q '"hits"'; then
    echo -e "${GREEN}✓ 基本搜索功能正常${NC}"
else
    echo -e "${YELLOW}⚠ 基本搜索功能可能有问题,但继续进行${NC}"
fi

# 输出环境信息
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}测试环境启动完成!${NC}"
echo -e "${GREEN}========================================${NC}"
echo -e "${BLUE}服务信息:${NC}"
echo "  Elasticsearch: $ES_HOST"
echo "  API服务: http://$API_HOST:$API_PORT"
echo "  测试客户: $CUSTOMER_ID"
echo -e "${BLUE}进程信息:${NC}"
echo "  API PID: $API_PID"
echo "  PID文件: $PID_FILE"
echo -e "${BLUE}日志文件:${NC}"
echo "  环境日志: $LOG_FILE"
echo "  API日志: $API_LOG_FILE"
echo "  ES日志: $ES_LOG_FILE"
echo -e "${BLUE}测试命令:${NC}"
echo "  运行所有测试: python scripts/run_tests.py"
echo "  单元测试: pytest tests/unit/ -v"
echo "  集成测试: pytest tests/integration/ -v"
echo "  API测试: pytest tests/integration/test_api_integration.py -v"
echo "e${NC}"
echo -e "${BLUE}停止环境: ./scripts/stop_test_environment.sh${NC}"

# 保存环境变量到文件供测试脚本使用
cat > "$PROJECT_ROOT/test_env.sh" << EOF
#!/bin/bash
export ES_HOST="$ES_HOST"
export ES_USERNAME="$ES_USERNAME"
export ES_PASSWORD="$ES_PASSWORD"
export API_HOST="$API_HOST"
export API_PORT="$API_PORT"
export CUSTOMER_ID="$CUSTOMER_ID"
export TESTING_MODE="$TESTING_MODE"
export LOG_LEVEL="$LOG_LEVEL"
export PYTHONPATH="$PROJECT_ROOT:\$PYTHONPATH"
EOF

chmod +x "$PROJECT_ROOT/test_env.sh"

echo -e "${GREEN}测试环境已准备就绪!${NC}"