性能回归测试脚本

```shellscript
#!/bin/bash

# 性能回归测试脚本
# 从指定 commit 开始,逐个测试性能问题

set -e

# 配置
START_COMMIT="d3232f4135fcb71be0376e99a5436f2ede079d05"
TEST_FILE="test/index.test.js"
TEST_TIMEOUT=80
TARGET_OUTPUT="/post/test/2000"

# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

echo -e "${YELLOW}开始性能回归测试...${NC}"
echo -e "${YELLOW}起始 commit: $START_COMMIT${NC}"
echo -e "${YELLOW}测试超时: ${TEST_TIMEOUT}秒${NC}"
echo -e "${YELLOW}目标输出: $TARGET_OUTPUT${NC}"

# 保存当前分支
ORIGINAL_BRANCH=$(git branch --show-current)
echo -e "${YELLOW}当前分支: $ORIGINAL_BRANCH${NC}"

# 备份原始测试文件
cp "$TEST_FILE" "${TEST_FILE}.backup"

# 获取从起始 commit 到当前的所有 commit
echo -e "${YELLOW}获取 commit 列表...${NC}"
COMMITS=($(git rev-list --reverse ${START_COMMIT}..HEAD))

# 添加起始 commit 到列表开头
COMMITS=("$START_COMMIT" "${COMMITS[@]}")

echo -e "${YELLOW}找到 ${#COMMITS[@]} 个 commit 需要测试${NC}"

# 清理函数
cleanup() {
    echo -e "\n${YELLOW}清理环境...${NC}"
    
    # 恢复原始测试文件
    if [ -f "${TEST_FILE}.backup" ]; then
        mv "${TEST_FILE}.backup" "$TEST_FILE"
        echo -e "${GREEN}已恢复原始测试文件${NC}"
    fi
    
    # 回到原始分支
    git checkout "$ORIGINAL_BRANCH" 2>/dev/null || true
    echo -e "${GREEN}已切换回原始分支: $ORIGINAL_BRANCH${NC}"
    
    # 停止可能还在运行的测试进程
    pkill -f "npm run test:dev" 2>/dev/null || true
    pkill -f "node.*test" 2>/dev/null || true
}

# 设置退出时清理
trap cleanup EXIT INT TERM

# 测试单个 commit 的函数
test_commit() {
    local commit=$1
    local commit_index=$2
    local total_commits=$3
    
    echo -e "\n${YELLOW}[${commit_index}/${total_commits}] 测试 commit: $commit${NC}"
    
    # 切换到指定 commit
    git checkout "$commit" --quiet
    
    # 获取 commit 信息
    local commit_msg=$(git log -1 --pretty=format:"%s" "$commit")
    local commit_date=$(git log -1 --pretty=format:"%ci" "$commit")
    echo -e "${YELLOW}提交信息: $commit_msg${NC}"
    echo -e "${YELLOW}提交时间: $commit_date${NC}"
    
    # 修改测试文件
    sed -i 's/describe\.skip('\''性能'\''/describe.only('\''性能'\''/g' "$TEST_FILE"
    
    if ! grep -q "describe\.only('性能'" "$TEST_FILE"; then
        echo -e "${RED}❌ 未能修改测试文件${NC}"
        return 1
    fi
    
    echo -e "${GREEN}✅ 已修改测试文件${NC}"
    
    # 创建临时文件存储输出
    local temp_output=$(mktemp)
    local test_pid
    
    echo -e "${YELLOW}开始运行测试...${NC}"
    
    # 在后台运行测试,使用 tee 实时输出到终端和文件
    timeout ${TEST_TIMEOUT}s npm run test:dev 2>&1 | tee "$temp_output" &
    test_pid=$!
    
    # 等待测试完成或超时
    local elapsed=0
    local found_target=false
    
    while [ $elapsed -lt $TEST_TIMEOUT ]; do
        sleep 1
        elapsed=$((elapsed + 1))
        
        # 检查是否找到目标输出
        if grep -q "$TARGET_OUTPUT" "$temp_output" 2>/dev/null; then
            found_target=true
            echo -e "\n${GREEN}✅ 在第 ${elapsed} 秒找到预期输出: $TARGET_OUTPUT${NC}"
            # 找到目标输出后立即跳出循环
            break
        fi
        
        # 检查进程是否还在运行
        if ! kill -0 $test_pid 2>/dev/null; then
            echo -e "\n${YELLOW}测试进程已结束${NC}"
            break
        fi
        
        # 显示进度(降低频率以免干扰实时输出)
        if [ $((elapsed % 10)) -eq 0 ]; then
            echo -e "\n${YELLOW}测试运行中... ${elapsed}/${TEST_TIMEOUT}秒${NC}"
        fi
    done
    
    # 停止测试进程及其子进程
    if kill -0 $test_pid 2>/dev/null; then
        # 停止整个进程组
        kill -TERM -$test_pid 2>/dev/null || true
        sleep 2
        kill -KILL -$test_pid 2>/dev/null || true
    fi
    wait $test_pid 2>/dev/null || true
    
    # 分析结果
    if [ "$found_target" = true ]; then
        echo -e "${GREEN}✅ 测试正常!找到了预期的输出: $TARGET_OUTPUT${NC}"
        echo -e "${GREEN}此 commit 没有性能问题,继续测试下一个...${NC}"
        
        rm -f "$temp_output"
        return 1  # 返回1继续测试下一个commit
    else
        echo -e "${RED}❌ 发现性能问题!${NC}"
        echo -e "${RED}在 ${TEST_TIMEOUT} 秒内未找到预期输出: $TARGET_OUTPUT${NC}"
        echo -e "${RED}🚨 这个 commit 导致了性能问题!${NC}"
        echo -e "${RED}问题 commit: $commit${NC}"
        echo -e "${RED}提交信息: $commit_msg${NC}"
        echo -e "${RED}提交时间: $commit_date${NC}"
        
        # 显示测试输出
        echo -e "\n${YELLOW}测试输出摘要:${NC}"
        tail -30 "$temp_output" || true
        
        rm -f "$temp_output"
        return 0  # 返回0表示找到了问题commit
    fi
}

# 主循环
echo -e "\n${YELLOW}开始逐个测试 commit...${NC}"

for i in "${!COMMITS[@]}"; do
    commit="${COMMITS[$i]}"
    commit_index=$((i + 1))
    total_commits=${#COMMITS[@]}
    
    if test_commit "$commit" "$commit_index" "$total_commits"; then
        echo -e "\n${RED}🚨 找到导致性能问题的 commit!${NC}"
        exit 0
    fi
    
    # 恢复测试文件以便下次测试
    git checkout HEAD -- "$TEST_FILE" 2>/dev/null || cp "${TEST_FILE}.backup" "$TEST_FILE"
done

echo -e "\n${GREEN}✅ 所有 commit 都测试完毕,未发现导致性能问题的版本${NC}"
echo -e "${GREEN}所有测试的 commit 都能正常找到预期输出${NC}"
exit 0

posted @ 2025-08-16 11:46  程序媛李李李李蕾  阅读(8)  评论(0)    收藏  举报