自动化测试报告优化:jenkins+jmeter定制化HTML报告生成

发布于:2025-07-10 ⋅ 阅读:(15) ⋅ 点赞:(0)

为什么需要定制化报告?

JMeter生成的HTML报告虽然功能完善,但关键信息不突出、展示不直观

如何实现

编写一个符合预期的shell脚本,在jenkins中通过shell步骤执行shell脚本来生成定制化html报告,后续可以通过归档至主节点,来进行展示等

shell脚本逻辑流程图:

在这里插入图片描述

shell脚本:

#!/bin/bash

# 【配置区】与 Jenkins HTML Publisher 配置对齐
# 工作空间根路径
WORKSPACE="/work/jenkins/workspace/Automated-testing/AgentJmeter-PublicAgent-release"  

# JMeter 相关路径
JMETER_JMX="$WORKSPACE/PublicAgent-release.jmx"       # 测试计划文件
JTL_FILE="$WORKSPACE/PublicAgent-release.jtl"  # JMeter 结果文件
HTML_REPORT_DIR="$WORKSPACE/html_report"  # JMeter 默认 HTML 报告输出目录  

# 自定义报告路径(与 HTML Publisher 配置一致)
CUSTOM_REPORT_DIR="$WORKSPACE/result_html"  
CUSTOM_HTML="$CUSTOM_REPORT_DIR/resultTotal.html"  # 索引页:resultTotal.html  

# JTL 文件字段列号(从 1 开始,与实际 JTL 表头严格对齐)
SUCCESS_COL=8        # success 字段所在列(第 8 列)
AGENT_NAME_COL=6     # 智能体名称所在列(threadName 列,第 6 列)
RESPONSE_MSG_COL=5   # responseMessage 字段所在列(第 5 列)
FAILURE_MSG_COL=9    # failureMessage 字段所在列(第 9 列)  

# 成功/失败标识值
SUCCESS_VALUE="true"
FAILURE_VALUE="false"  


# 【函数区】模块化封装核心逻辑
# 1. 日志打印函数(带时间戳,便于调试)
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}

# 2. 清理旧文件/目录(健壮性处理:rm -rf 避免目录不存在报错)
clean_old_resources() {
    log "开始清理旧文件/目录..."
    rm -rf "$HTML_REPORT_DIR"/*   # 清理 JMeter 默认报告
    rm -rf "$JTL_FILE"            # 清理旧 JTL 文件
    rm -rf "$CUSTOM_REPORT_DIR"   # 强制删除自定义报告目录(无则忽略)
    mkdir -p "$CUSTOM_REPORT_DIR" # 重建自定义报告目录(确保父目录存在)
    log "旧文件/目录清理完成"
}

# 3. 运行 JMeter 生成测试结果 + 默认 HTML 报告
run_jmeter_test() {
    log "开始运行 JMeter 测试..."
    jmeter -n -t "$JMETER_JMX" \
           -l "$JTL_FILE" \
           -e \
           -o "$HTML_REPORT_DIR"
    # 检查 JMeter 执行返回码(非 0 则失败)
    if [ $? -ne 0 ]; then
        log "× JMeter 执行失败,脚本终止"
        exit 1
    fi
    log "JMeter 测试执行完成,JTL 和默认报告已生成"
}

# 4. 解析 JTL 统计成功/失败数(处理多行字段)
parse_jtl_summary() {
    log "开始解析 JTL 统计成功/失败数..."
    # 使用 awk 解析 JTL,注意分隔符和引号处理
    local result=$(awk -v FPAT='([^,]*)|("[^"]*")' -v s_col="$SUCCESS_COL" -v s_val="$SUCCESS_VALUE" -v f_val="$FAILURE_VALUE" '
    NR > 1 {
        gsub(/^"|"$/, "", $s_col);  # 移除字段前后引号(JTL 带引号时保留)
        if ($s_col == s_val) count_success++
        else if ($s_col == f_val) count_failure++
    }
    END {
        print count_success+0, count_failure+0  # 强制转数字,避免空值
    }' "$JTL_FILE")
    
    # 新增调试日志,查看 awk 输出
    log "DEBUG: awk 返回的 success/failure 数: [$result]"  
    
    # 按空格分割 awk 输出(awk 用 print 输出时默认空格分隔)
    IFS=' ' read -r SUCCESS_COUNT FAILURE_COUNT <<< "$result"  
    
    # 计算总数(此时 SUCCESS_COUNT/FAILURE_COUNT 应为纯数字)
    TOTAL_COUNT=$((SUCCESS_COUNT + FAILURE_COUNT))
    log "成功数: $SUCCESS_COUNT, 失败数: $FAILURE_COUNT, 总数: $TOTAL_COUNT"
}

# 5. 计算成功率
calculate_success_rate() {
    log "计算成功率..."
    if [ "$TOTAL_COUNT" -eq 0 ]; then
        SUCCESS_RATE="0.00"
    else
        SUCCESS_RATE=$(awk -v s="$SUCCESS_COUNT" -v t="$TOTAL_COUNT" 'BEGIN { printf "%.2f", (s/t)*100 }')
    fi
    log "成功率: $SUCCESS_RATE%"
}

# 6. 提取失败详情
parse_failure_details() {
    awk -v FPAT='([^,]*)|("[^"]*")' -v s_col="$SUCCESS_COL" -v f_val="$FAILURE_VALUE" -v agent_col="$AGENT_NAME_COL" -v msg_col="$FAILURE_MSG_COL" '
    NR == 1 { next }  # 跳过表头行
    {
        success_val = $s_col;
        gsub(/^"|"$/, "", success_val);
        if (success_val == f_val) {
            agent_name = $agent_col;
            gsub(/^"|"$/, "", agent_name);
            split(agent_name, parts, "^");
            failure_msg = $msg_col;
            gsub(/^"|"$/, "", failure_msg);
            gsub(/\n/, "<br>", failure_msg);
            gsub(/&/, "&amp;", failure_msg);
            gsub(/</, "&lt;", failure_msg);
            gsub(/>/, "&gt;", failure_msg);
            printf "<tr class=\"failure-row\"><td>%s</td><td>%s</td><td>%s</td></tr>\n", parts[1], parts[2], failure_msg;
        }
    }' "$JTL_FILE"
}

# 7. 提取成功详情
parse_success_details() {
    awk -v FPAT='([^,]*)|("[^"]*")' -v s_col="$SUCCESS_COL" -v s_val="$SUCCESS_VALUE" -v agent_col="$AGENT_NAME_COL" -v msg_col="$RESPONSE_MSG_COL" '
    NR == 1 { next }  # 跳过表头行
    {
        success_val = $s_col;
        gsub(/^"|"$/, "", success_val);
        if (success_val == s_val) {
            agent_name = $agent_col;
            gsub(/^"|"$/, "", agent_name);
            split(agent_name, parts, "^");
            response_msg = $msg_col;
            gsub(/^"|"$/, "", response_msg);
            gsub(/\n/, "<br>", response_msg);
            gsub(/&/, "&amp;", response_msg);
            gsub(/</, "&lt;", response_msg);
            gsub(/>/, "&gt;", response_msg);
            printf "<tr class=\"success-row\"><td>%s</td><td>%s</td><td>%s</td></tr>\n", parts[1], parts[2], response_msg;
        }
    }' "$JTL_FILE"
}

# 8. 生成自定义 HTML 报告
generate_custom_report() {
    log "开始生成自定义报告: $CUSTOM_HTML"
    # 使用 HEREDOC 生成 HTML 内容,嵌入统计变量和详情
    cat <<EOF > "$CUSTOM_HTML"
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>执行结果统计</title>
    <style>
    	# css样式
        body { font-family: Arial, sans-serif; padding: 20px; background-color: #f9f9f9; }
        h2 { color: #333; border-bottom: 2px solid #ddd; padding-bottom: 10px; }
        table { border-collapse: collapse; width: 90%; margin: 20px 0; box-shadow: 0 2px 8px rgba(0,0,0,0.1); background-color: white; }
        th, td { padding: 12px; text-align: left; border: 1px solid #ddd; }
        th { background-color: #f2f2f2; color: #333; font-weight: bold; }
        .success-row { background-color: #d4f4dd; color: green; }
        .failure-row { background-color: #f8cccc; color: red; }
        .total-row { background-color: #e6e6fa; font-weight: bold; }
        .rate-row { background-color: #fffacd; }
        .details-table { width: 100%; }
        .details-table td, .details-table th { vertical-align: top; }
        pre { white-space: pre-wrap; word-wrap: break-word; background-color: #f0f0f0; padding: 10px; border: 1px solid #ccc; border-radius: 4px; }
    </style>
</head>
<body>
<h2>执行结果统计</h2>
<table>
    <tr class="success-row">
        <th>统计项</th>
        <th>统计值</th>
    </tr>
    <tr class="success-row">
        <td>成功数</td>
        <td>$SUCCESS_COUNT</td>
    </tr>
    <tr class="failure-row">
        <td>失败数</td>
        <td>$FAILURE_COUNT</td>
    </tr>
    <tr class="total-row">
        <td>总数</td>
        <td>$TOTAL_COUNT</td>
    </tr>
    <tr class="rate-row">
        <td>成功率</td>
        <td>$SUCCESS_RATE%</td>
    </tr>
</table>

<h2>执行结果数据</h2>
<table class="details-table">
    <tr>
        <th>智能体名称</th> 
        <th>Query</th>
        <th style="width:60%">详细信息</th> 
    </tr>
$(parse_failure_details)$(parse_success_details)
</table>
</body>
</html>
EOF
    # 确保报告文件权限(Jenkins 可访问)
    chmod 644 "$CUSTOM_HTML"
    log "自定义报告生成完成:$CUSTOM_HTML"
}

# 9. 检验报告文件是否生成
verify_report() {
    if [ -f "$CUSTOM_HTML" ]; then
        log "报告验证通过:$CUSTOM_HTML 存在"
    else
        log "错误:$CUSTOM_HTML 生成失败"
        exit 1
    fi
}


# 【主流程】按顺序执行函数
main() {
    clean_old_resources
    run_jmeter_test
    parse_jtl_summary
    calculate_success_rate
    generate_custom_report
    verify_report
}

# 启动主流程
main

定制化html页面总览:

在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到