JMeter 自动化测试 + 飞书通知完整指南
从零开始搭建 JMeter 自动化测试系统,并通过飞书机器人实时推送测试报告
📖 目录
- 项目简介
- 系统架构
- 环境准备
- 配置参数说明
- 实施步骤
- 代码实现
- 常见问题
- 最佳实践
项目简介
背景
在持续集成/持续部署(CI/CD)流程中,自动化测试是保证代码质量的重要环节。本项目实现了:
- ✅ 自动化执行:批量运行 JMeter 测试脚本
- ✅ 智能分析:自动统计成功率、响应时间、失败详情
- ✅ 实时通知:测试完成后立即推送飞书消息
- ✅ 可视化报告:美观的飞书卡片样式报告
技术栈
- 测试工具:Apache JMeter 5.6.3
- 开发语言:Python 3.7+
- 依赖库:pandas、requests
- 通知渠道:飞书自定义机器人
效果展示
1📊 测试执行总览 2🎉 执行状态:全部通过 3📈 测试脚本:3 个 (成功执行: 3个, 执行失败: 0个) 4🎯 接口统计:总计 150个, 成功 148个, 失败 2个 5📊 整体成功率:98.7% 6⏱️ 总耗时:5分32秒 7
系统架构
架构图
1┌─────────────────┐ 2│ JMeter 脚本 │ 3│ (.jmx 文件) │ 4└────────┬────────┘ 5 │ 6 ▼ 7┌─────────────────┐ 8│ Python 调度器 │ 9│ 批量执行测试 │ 10└────────┬────────┘ 11 │ 12 ├──► 1. 执行 JMeter 命令 13 ├──► 2. 收集 CSV 结果 14 ├──► 3. 分析测试数据 15 └──► 4. 生成飞书报告 16 │ 17 ▼ 18 ┌──────────────┐ 19 │ 飞书机器人 │ 20 │ 推送通知 │ 21 └──────────────┘ 22
工作流程
- 扫描测试脚本:自动发现指定目录下的所有
.jmx文件 - 顺序执行测试:调用 JMeter 命令行逐个执行测试
- 结果收集分析:读取 CSV 结果文件,统计成功率、响应时间等
- 生成测试报告:汇总所有测试结果,格式化为 Markdown
- 发送飞书通知:通过 Webhook 推送卡片样式的报告
环境准备
硬件要求
- 操作系统:Linux(推荐 CentOS 7+ / Ubuntu 18.04+)
- 内存:至少 2GB
- 磁盘:至少 5GB 可用空间
软件依赖
| 软件 | 版本要求 | 说明 |
|---|---|---|
| Python | 3.7+ | 运行调度脚本 |
| JMeter | 5.6.2+ | 执行性能测试 |
| Java | 8+ | JMeter 运行依赖 |
配置参数说明
1. 飞书机器人配置
1.1 创建飞书自定义机器人
步骤:
- 打开飞书,进入目标群聊
- 点击右上角 「设置」 → 「群机器人」
- 选择 「添加机器人」 → 「自定义机器人」
- 填写机器人信息:
- 名称:
JMeter 测试报告 - 描述:
自动推送接口测试结果
- 名称:
- 安全设置:勾选 「签名校验」
- 点击 「完成」,获取以下信息:
获取到的配置:
1# Webhook URL(示例,实际请替换为你的) 2webhook = "https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" 3 4# 签名密钥 Secret(示例,实际请替换为你的) 5secret = "YourSecretKeyHere123456" 6
1.2 参数获取位置
| 参数 | 获取方式 | 示例值 |
|---|---|---|
| webhook | 创建机器人后显示的 Webhook 地址 | https://open.feishu.cn/open-apis/bot/v2/hook/xxx... |
| secret | 启用签名校验后显示的密钥 | YourSecretKeyHere123456 |
注意事项:
- ⚠️ 请妥善保管
webhook和secret,避免泄露 - ⚠️ 建议使用环境变量或配置文件存储,不要硬编码在代码中
- ⚠️ 每个机器人的配置是唯一的,不同群需要创建不同的机器人
2. JMeter 配置
2.1 JMeter 安装路径
Linux 安装步骤:
1# 1. 下载 JMeter(使用国内镜像加速) 2cd /home/your-user 3wget https://mirrors.tuna.tsinghua.edu.cn/apache/jmeter/binaries/apache-jmeter-5.6.3.tgz 4 5# 2. 解压 6tar -xzf apache-jmeter-5.6.3.tgz 7 8# 3. 验证安装 9/home/your-user/apache-jmeter-5.6.3/bin/jmeter -v 10
配置参数:
1# JMeter 可执行文件的完整路径 2JMETER_BIN = "/home/your-user/apache-jmeter-5.6.3/bin/jmeter" 3
2.2 如何获取 JMeter 路径
1# 方法1:使用 which 命令(如果已加入 PATH) 2which jmeter 3 4# 方法2:使用 find 命令查找 5find /home -name "jmeter" -type f 2>/dev/null 6 7# 方法3:查看安装目录 8ls -la /home/your-user/apache-jmeter-*/bin/jmeter 9
3. 目录结构配置
3.1 推荐的目录结构
1/home/your-user/cicd/ 2├── test/ 3│ ├── testscript/ # 存放 .jmx 测试脚本 4│ │ ├── test_api1.jmx 5│ │ ├── test_api2.jmx 6│ │ └── logs/ # JMeter 执行日志 7│ └── logs/ # CSV 测试结果 8├── jmeter_automation.py # Python 主程序 9└── clean_jmx.py # JMX 文件清理工具 10
3.2 目录配置参数
1# 测试脚本存放目录 2TEST_SCRIPT_DIR = "/home/your-user/cicd/test/testscript" 3 4# CSV 结果文件输出目录 5CSV_LOG_DIR = "/home/your-user/cicd/test/logs" 6 7# JMeter 执行日志目录 8JMETER_LOG_DIR = "/home/your-user/cicd/test/testscript/logs" 9
3.3 创建目录结构
1# 创建所需目录 2mkdir -p /home/your-user/cicd/test/testscript 3mkdir -p /home/your-user/cicd/test/logs 4mkdir -p /home/your-user/cicd/test/testscript/logs 5 6# 设置权限 7chmod -R 755 /home/your-user/cicd 8
4. 完整配置清单
创建配置文件 config.py:
1# -*- coding: utf-8 -*- 2""" 3JMeter 自动化测试配置文件 4请根据实际环境修改以下配置 5""" 6 7# ==================== 飞书机器人配置 ==================== 8# 获取方式:飞书群聊 → 设置 → 群机器人 → 添加自定义机器人 9FEISHU_WEBHOOK = "https://open.feishu.cn/open-apis/bot/v2/hook/YOUR_WEBHOOK_ID" 10FEISHU_SECRET = "YOUR_SECRET_KEY" 11 12# ==================== JMeter 配置 ==================== 13# JMeter 可执行文件路径 14# 获取方式:执行 'which jmeter' 或 'find /home -name jmeter' 15JMETER_BIN = "/home/your-user/apache-jmeter-5.6.3/bin/jmeter" 16 17# ==================== 目录配置 ==================== 18# 测试脚本目录(存放 .jmx 文件) 19TEST_SCRIPT_DIR = "/home/your-user/cicd/test/testscript" 20 21# CSV 结果输出目录 22CSV_LOG_DIR = "/home/your-user/cicd/test/logs" 23 24# JMeter 日志目录 25JMETER_LOG_DIR = "/home/your-user/cicd/test/testscript/logs" 26 27# ==================== 执行配置 ==================== 28# 单个测试超时时间(秒) 29TEST_TIMEOUT = 600 # 10分钟 30 31# 是否使用飞书卡片样式 32USE_CARD_STYLE = True 33
配置验证检查清单:
1# 检查 JMeter 是否可用 2/home/your-user/apache-jmeter-5.6.3/bin/jmeter -v 3 4# 检查目录是否存在 5ls -la /home/your-user/cicd/test/testscript 6 7# 检查 Python 依赖 8python3 -c "import pandas, requests; print('依赖检查通过')" 9 10# 测试飞书 Webhook(可选) 11curl -X POST "$FEISHU_WEBHOOK" \ 12 -H 'Content-Type: application/json' \ 13 -d '{"msg_type":"text","content":{"text":"测试消息"}}' 14
实施步骤
第一步:环境安装
1.1 安装 Python 依赖
1# 安装 pandas 和 requests 2pip3 install pandas requests 3 4# 或使用 requirements.txt 5cat > requirements.txt <<EOF 6pandas>=1.3.0 7requests>=2.25.0 8EOF 9 10pip3 install -r requirements.txt 11
1.2 安装 JMeter
1# 使用清华镜像下载(速度快) 2cd /home/your-user 3wget https://mirrors.tuna.tsinghua.edu.cn/apache/jmeter/binaries/apache-jmeter-5.6.3.tgz 4 5# 解压 6tar -xzf apache-jmeter-5.6.3.tgz 7 8# 验证 9./apache-jmeter-5.6.3/bin/jmeter -v 10
第二步:创建飞书机器人
2.1 操作步骤
- 打开飞书客户端
- 进入要接收通知的群聊
- 点击群设置 → 群机器人 → 添加机器人
- 选择"自定义机器人"
- 配置:
- 名称:
JMeter 自动化测试报告 - 启用签名校验:✅
- 名称:
- 保存 Webhook URL 和 Secret
2.2 验证机器人
1# 发送测试消息 2WEBHOOK="你的webhook地址" 3SECRET="你的secret" 4TIMESTAMP=$(date +%s) 5 6# 生成签名 7SIGN=$(echo -ne "${TIMESTAMP}\n${SECRET}" | openssl dgst -sha256 -hmac "" -binary | base64) 8 9# 发送消息 10curl -X POST "$WEBHOOK" \ 11 -H 'Content-Type: application/json' \ 12 -d "{ 13 \"timestamp\": $TIMESTAMP, 14 \"sign\": \"$SIGN\", 15 \"msg_type\": \"text\", 16 \"content\": {\"text\": \"✅ 飞书机器人配置成功!\"} 17 }" 18
第三步:准备测试脚本
3.1 创建目录结构
1mkdir -p /home/your-user/cicd/test/testscript 2mkdir -p /home/your-user/cicd/test/logs 3mkdir -p /home/your-user/cicd/test/testscript/logs 4
3.2 上传 JMX 文件
1# 从本地上传(在 Windows 执行) 2scp your-test.jmx user@server:/home/your-user/cicd/test/testscript/ 3
3.3 清理 JMX 文件中的第三方插件(重要!)
问题说明:
JMeter 脚本可能包含第三方可视化插件(如 kg.apc.jmeter.vizualizers.*),这些插件:
- 只在 GUI 模式下有用
- 命令行模式不需要
- 如果缺少插件会导致执行失败
解决方案:清理可视化组件
1# 方法1:使用 sed 命令清理 2cd /home/your-user/cicd/test/testscript 3cp your-test.jmx your-test.jmx.bak # 备份 4 5sed -i '/<kg\.apc\.jmeter\.vizualizers/,/<\/kg\.apc\.jmeter\.vizualizers/d' your-test.jmx 6 7# 方法2:使用 Python 清理脚本(推荐) 8python3 clean_jmx.py your-test.jmx 9
验证清理效果:
1# 检查是否还有第三方插件引用 2grep "kg.apc.jmeter" your-test.jmx 3 4# 如果无输出,说明清理成功 5 6# 测试运行 7/home/your-user/apache-jmeter-5.6.3/bin/jmeter \ 8 -n -t your-test.jmx -l test.csv -j test.log 9
第四步:部署 Python 脚本
4.1 上传脚本
1# 上传主程序 2scp jmeter_automation.py user@server:/home/your-user/cicd/ 3 4# 上传配置文件 5scp config.py user@server:/home/your-user/cicd/ 6
4.2 修改配置
1# 编辑配置文件 2vim /home/your-user/cicd/config.py 3 4# 修改以下配置: 5# 1. FEISHU_WEBHOOK - 改为你的 webhook 地址 6# 2. FEISHU_SECRET - 改为你的 secret 7# 3. JMETER_BIN - 改为你的 JMeter 路径 8# 4. TEST_SCRIPT_DIR - 改为你的脚本目录 9
第五步:运行测试
5.1 手动执行
1cd /home/your-user/cicd 2python3 jmeter_automation.py 3
预期输出示例:
1🚀 JMeter 自动化测试开始 2================================================== 3📋 找到 3 个测试脚本,开始批量执行... 4 5[1/3] 正在处理:test_api_login.jmx 6🚀 开始执行:test_api_login.jmx 7✅ 完成执行:test_api_login.jmx,耗时:1分23秒 8 9[2/3] 正在处理:test_api_search.jmx 10🚀 开始执行:test_api_search.jmx 11✅ 完成执行:test_api_search.jmx,耗时:2分15秒 12 13================================================== 14📊 所有测试执行完成,生成报告... 15📤 正在发送报告到飞书... 16✅ 飞书报告发送成功! 17 18🎉 所有任务完成! 19
5.2 设置定时任务(使用 crontab)
什么是 Crontab?
Crontab 是 Linux 系统的定时任务工具,可以让脚本在指定时间自动运行。
操作步骤:
1# 1. 编辑定时任务 2crontab -e 3
首次使用会让你选择编辑器:
1Select an editor. To change later, run 'select-editor'. 2 1. /bin/nano <---- 最简单,推荐新手 3 2. /usr/bin/vim.basic 4 3. /usr/bin/vim.tiny 5 6Choose 1-3 [1]: 1 # 输入 1 选择 nano 编辑器 7
添加定时任务:
在打开的编辑器中,添加以下内容(根据需求选择):
1# ==================== 定时任务示例 ==================== 2 3# 每天上午 9 点执行测试 40 9 * * * /usr/bin/python3 /home/your-user/cicd/jmeter_automation.py >> /home/your-user/cicd/cron.log 2>&1 5 6# 每天凌晨 2 点执行测试 70 2 * * * /usr/bin/python3 /home/your-user/cicd/jmeter_automation.py >> /home/your-user/cicd/cron.log 2>&1 8 9# 每周一上午 9 点执行 100 9 * * 1 /usr/bin/python3 /home/your-user/cicd/jmeter_automation.py >> /home/your-user/cicd/cron.log 2>&1 11 12# 每小时执行一次 130 * * * * /usr/bin/python3 /home/your-user/cicd/jmeter_automation.py >> /home/your-user/cicd/cron.log 2>&1 14 15# 工作日(周一到周五)上午 10 点执行 160 10 * * 1-5 /usr/bin/python3 /home/your-user/cicd/jmeter_automation.py >> /home/your-user/cicd/cron.log 2>&1 17
Crontab 时间格式说明:
1 ┌───────────── 分钟 (0 - 59) 2 │ ┌───────────── 小时 (0 - 23) 3 │ │ ┌───────────── 日期 (1 - 31) 4 │ │ │ ┌───────────── 月份 (1 - 12) 5 │ │ │ │ ┌───────────── 星期 (0 - 7, 0 和 7 都表示周日) 6 │ │ │ │ │ 7 * * * * * 要执行的命令 8
常用时间表达式:
| 表达式 | 说明 | 示例 |
|---|---|---|
| 0 9 * * * | 每天 9:00 | 上午 9 点整 |
| 30 14 * * * | 每天 14:30 | 下午 2:30 |
| 0 */2 * * * | 每 2 小时 | 0:00, 2:00, 4:00… |
| 0 9 * * 1 | 每周一 9:00 | 周一上午 9 点 |
| 0 9 1 * * | 每月 1 号 9:00 | 每月第一天 |
| 0 9 * * 1-5 | 工作日 9:00 | 周一到周五 |
保存并退出编辑器:
方式一:使用 nano 编辑器(推荐新手)
11. 添加完定时任务后 22. 按 Ctrl + X(退出) 33. 提示 "Save modified buffer?" 时,按 Y(保存) 44. 提示 "File Name to Write" 时,直接按 Enter(确认) 55. 看到 "crontab: installing new crontab" 表示成功 6
方式二:使用 vim 编辑器
11. 添加完定时任务后 22. 按 Esc 键(进入命令模式) 33. 输入 :wq 然后按 Enter(保存并退出) 4 5# 不保存退出 6Esc → :q! → Enter 7
快捷键总结:
| 编辑器 | 保存并退出 | 不保存退出 |
|---|---|---|
| nano | Ctrl + X → Y → Enter | Ctrl + X → N |
| vim | Esc → :wq → Enter | Esc → :q! → Enter |
验证定时任务:
1# 查看当前用户的定时任务 2crontab -l 3 4# 查看 crontab 服务状态 5systemctl status cron # Ubuntu/Debian 6systemctl status crond # CentOS/RHEL 7 8# 查看 crontab 执行日志 9tail -f /var/log/cron # CentOS/RHEL 10tail -f /var/log/syslog # Ubuntu/Debian 11 12# 查看自定义的执行日志 13tail -f /home/your-user/cicd/cron.log 14
常用 crontab 命令:
1crontab -e # 编辑定时任务 2crontab -l # 列出所有定时任务 3crontab -r # 删除所有定时任务(谨慎使用!) 4crontab -u user -e # 编辑指定用户的定时任务(需要 root 权限) 5
测试定时任务(可选):
如果想立即测试定时任务是否正常工作,可以临时设置一个1分钟后执行的任务:
1# 1. 查看当前时间 2date 3 4# 假设现在是 14:30,那么设置 14:31 执行 5crontab -e 6 7# 添加(1分钟后执行) 831 14 * * * /usr/bin/python3 /home/your-user/cicd/jmeter_automation.py >> /home/your-user/cicd/test.log 2>&1 9 10# 2. 等待 1 分钟后查看日志 11tail -f /home/your-user/cicd/test.log 12 13# 3. 测试成功后,删除测试任务 14crontab -e # 删除刚才添加的测试行 15
注意事项:
⚠️ 路径必须使用绝对路径
1# ✅ 正确 20 9 * * * /usr/bin/python3 /home/your-user/cicd/jmeter_automation.py 3 4# ❌ 错误(相对路径在 crontab 中不工作) 50 9 * * * python3 jmeter_automation.py 6
⚠️ 指定完整的 Python 解释器路径
1# 查找 Python3 的完整路径 2which python3 3# 输出:/usr/bin/python3 4 5# 在 crontab 中使用完整路径 6/usr/bin/python3 /path/to/script.py 7
⚠️ 重定向日志输出
1# >> cron.log 2>&1 的含义: 2# >> cron.log - 将标准输出追加到 cron.log 3# 2>&1 - 将错误输出也重定向到标准输出(即同一个文件) 4 5# 这样可以在日志文件中看到所有输出和错误信息 6
⚠️ 时区问题
1# 检查服务器时区 2date 3timedatectl 4 5# 如果时区不对,修改时区(以中国为例) 6sudo timedatectl set-timezone Asia/Shanghai 7
代码实现
核心代码结构
1# -*- coding: utf-8 -*- 2import hashlib, base64, hmac, requests 3import pandas as pd 4import time, os, subprocess, json 5from datetime import datetime 6 7# ==================== 配置部分 ==================== 8# 从配置文件导入或直接定义 9from config import ( 10 FEISHU_WEBHOOK, 11 FEISHU_SECRET, 12 JMETER_BIN, 13 TEST_SCRIPT_DIR, 14 CSV_LOG_DIR, 15 JMETER_LOG_DIR, 16 TEST_TIMEOUT, 17 USE_CARD_STYLE 18) 19 20# ==================== 飞书签名生成 ==================== 21def gen_sign(timestamp, secret): 22 """生成飞书机器人签名""" 23 string_to_sign = f'{timestamp}\n{secret}' 24 hmac_code = hmac.new( 25 string_to_sign.encode(), 26 digestmod=hashlib.sha256 27 ).digest() 28 return base64.b64encode(hmac_code).decode() 29 30# ==================== 发送飞书消息 ==================== 31def send_message(timestamp, sign_id, content_blocks, use_card_style=False): 32 """发送消息到飞书""" 33 url = webhook 34 headers = {'Content-Type': 'application/json'} 35 36 if use_card_style: 37 # 使用卡片样式 38 # 将content_blocks转换为markdown文本 39 markdown_content = "" 40 for block in content_blocks: 41 if block and len(block) > 0 and "text" in block[0]: 42 text = block[0]["text"] 43 if text.strip(): # 只添加非空文本 44 markdown_content += text + "\n\n" 45 46 data = { 47 "timestamp": timestamp, 48 "sign": sign_id, 49 "msg_type": "interactive", 50 "card": { 51 "schema": "2.0", 52 "config": { 53 "update_multi": True, 54 "style": { 55 "text_size": { 56 "normal_v2": { 57 "default": "normal", 58 "pc": "normal", 59 "mobile": "heading" 60 } 61 } 62 } 63 }, 64 "body": { 65 "direction": "vertical", 66 "padding": "16px 16px 16px 16px", 67 "elements": [ 68 { 69 "tag": "markdown", 70 "content": markdown_content, 71 "text_align": "left", 72 "text_size": "normal_v2", 73 "margin": "0px 0px 0px 0px" 74 } 75 ] 76 }, 77 "header": { 78 "title": { 79 "tag": "plain_text", 80 "content": "🧪 JMeter 自动化测试报告" 81 }, 82 "subtitle": { 83 "tag": "plain_text", 84 "content": f"执行时间:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}" 85 }, 86 "template": "blue", 87 "padding": "12px 12px 12px 12px" 88 } 89 } 90 } 91 else: 92 # 使用原来的post样式 93 data = { 94 "timestamp": timestamp, 95 "sign": sign_id, 96 "msg_type": "post", 97 "content": { 98 "post": { 99 "zh_cn": { 100 "title": "🧪 JMeter 自动化测试报告", 101 "content": content_blocks 102 } 103 } 104 } 105 } 106 107 # 打印调试信息 108 print("发送的数据结构:") 109 print(json.dumps(data, ensure_ascii=False, indent=2)) 110 111 response = requests.post(url, headers=headers, json=data) 112 return response.json() 113 114# ==================== 执行 JMeter 测试 ==================== 115def run_jmeter_script(jmx_file): 116 """运行 JMeter 脚本""" 117 start_time = time.time() 118 current_time = datetime.now().strftime("%Y_%m_%d_%H_%M_%S") 119 name = os.path.basename(jmx_file) 120 121 result_csv = f"{CSV_LOG_DIR}/{name}_{current_time}.csv" 122 result_log = f"{JMETER_LOG_DIR}/{name}_{current_time}.log" 123 124 # 创建日志目录 125 os.makedirs(os.path.dirname(result_csv), exist_ok=True) 126 os.makedirs(os.path.dirname(result_log), exist_ok=True) 127 128 cmd = [ 129 JMETER_BIN, 130 "-n", "-t", jmx_file, 131 "-l", result_csv, 132 "-j", result_log 133 ] 134 135 print(f"🚀 开始执行:{name}") 136 try: 137 subprocess.run(cmd, check=True, timeout=TEST_TIMEOUT) 138 duration = time.time() - start_time 139 print(f"✅ 完成执行:{name},耗时:{format_duration(duration)}") 140 return result_csv, duration 141 except subprocess.TimeoutExpired: 142 print(f"⏰ 执行超时:{name}") 143 return None, None 144 except subprocess.CalledProcessError as e: 145 print(f"❌ 执行失败:{name},错误:{e}") 146 return None, None 147 148# ==================== 分析测试结果 ==================== 149def analyze_csv_results(csv_file): 150 """分析 CSV 结果文件""" 151 try: 152 df = pd.read_csv(csv_file) 153 154 total_requests = len(df) 155 success_requests = len(df[df['success'] == True]) 156 failed_requests = len(df[df['success'] == False]) 157 success_rate = (success_requests / total_requests * 100) if total_requests > 0 else 0 158 avg_response_time = df['elapsed'].mean() if 'elapsed' in df.columns else 0 159 160 # 获取失败详情 161 failed_details = [] 162 if failed_requests > 0: 163 failed = df[df["success"] == False] 164 for _, row in failed.iterrows(): 165 failed_details.append({ 166 'label': str(row.get("label")), 167 'responseCode': str(row.get("responseCode")), 168 'failureMessage': str(row.get("failureMessage")), 169 'url': str(row.get("URL")) 170 }) 171 172 return { 173 'total': total_requests, 174 'success': success_requests, 175 'failed': failed_requests, 176 'success_rate': success_rate, 177 'avg_response_time': avg_response_time, 178 'failed_details': failed_details 179 } 180 except Exception as e: 181 print(f"分析 CSV 文件失败:{str(e)}") 182 return None 183 184# ==================== 主函数 ==================== 185def main(): 186 """主函数""" 187 print("🚀 JMeter 自动化测试开始") 188 start_time = time.time() 189 190 # 获取所有 JMX 文件 191 jmx_files = sorted([ 192 os.path.join(TEST_SCRIPT_DIR, f) 193 for f in os.listdir(TEST_SCRIPT_DIR) 194 if f.endswith(".jmx") 195 ]) 196 197 if not jmx_files: 198 print(f"⚠️ 警告:在 {TEST_SCRIPT_DIR} 中没有找到任何 .jmx 文件") 199 return 200 201 print(f"📋 找到 {len(jmx_files)} 个测试脚本") 202 203 # 执行所有测试 204 results = [] 205 for jmx in jmx_files: 206 result_csv, duration = run_jmeter_script(jmx) 207 analysis = analyze_csv_results(result_csv) if result_csv else None 208 209 results.append({ 210 'name': os.path.basename(jmx), 211 'duration': duration or 0, 212 'analysis': analysis, 213 'status': 'success' if analysis else 'failed' 214 }) 215 216 # 生成并发送报告 217 # ... 详见完整代码 218 219 print("🎉 所有任务完成!") 220 221if __name__ == "__main__": 222 main() 223
常见问题
1. JMeter 执行失败:找不到插件
错误信息:
1CannotResolveClassException: kg.apc.jmeter.vizualizers.CorrectedResultCollector 2
原因: JMX 文件中包含第三方可视化插件
解决方案:
1# 清理 JMX 文件中的可视化组件 2sed -i '/<kg\.apc\.jmeter\.vizualizers/,/<\/kg\.apc\.jmeter\.vizualizers/d' your-test.jmx 3
2. 飞书消息发送失败
错误代码: code: 19021
原因: 签名验证失败
解决方案:
- 检查
secret是否正确 - 检查时间戳是否为当前时间(秒级)
- 检查签名生成算法是否正确
1# 正确的签名生成 2timestamp = int(time.time()) # 必须是整数秒 3string_to_sign = f'{timestamp}\n{secret}' 4hmac_code = hmac.new(string_to_sign.encode(), digestmod=hashlib.sha256).digest() 5sign = base64.b64encode(hmac_code).decode() 6
3. CSV 文件无法解析
错误信息: KeyError: 'success'
原因: JMeter 配置未正确输出结果
解决方案:
确保 JMeter 脚本中包含"简单数据写入器"或正确的监听器配置:
1<ResultCollector guiclass="SimpleDataWriter" testclass="ResultCollector"> 2 <objProp> 3 <value class="SampleSaveConfiguration"> 4 <time>true</time> 5 <latency>true</latency> 6 <success>true</success> 7 <label>true</label> 8 <code>true</code> 9 <message>true</message> 10 <responseData>false</responseData> 11 </value> 12 </objProp> 13</ResultCollector> 14
4. 权限问题
错误信息: Permission denied
解决方案:
1# 给脚本执行权限 2chmod +x jmeter_automation.py 3 4# 给目录写权限 5chmod -R 755 /home/your-user/cicd 6
最佳实践
1. 安全性建议
1.1 敏感信息管理
不推荐:硬编码
1webhook = "https://open.feishu.cn/open-apis/bot/v2/hook/xxx" # ❌ 2secret = "my-secret-key" # ❌ 3
推荐:使用环境变量
1import os 2 3webhook = os.getenv('FEISHU_WEBHOOK') 4secret = os.getenv('FEISHU_SECRET') 5
1# 设置环境变量 2export FEISHU_WEBHOOK="https://open.feishu.cn/..." 3export FEISHU_SECRET="your-secret" 4 5# 或写入 .env 文件 6echo 'FEISHU_WEBHOOK="https://..."' >> .env 7echo 'FEISHU_SECRET="xxx"' >> .env 8
推荐:使用配置文件 + .gitignore
1# config.py (加入 .gitignore) 2FEISHU_WEBHOOK = "..." 3FEISHU_SECRET = "..." 4
1# .gitignore 2config.py 3*.pyc 4__pycache__/ 5
1.2 Webhook 访问控制
- 仅在受信任的服务器上部署
- 定期轮换 Secret 密钥
- 限制机器人权限(只读群聊信息)
2. 性能优化
2.1 并行执行测试(可选)
1from concurrent.futures import ThreadPoolExecutor 2 3def main(): 4 jmx_files = [...] 5 6 # 使用线程池并行执行(谨慎使用,可能导致资源竞争) 7 with ThreadPoolExecutor(max_workers=3) as executor: 8 futures = [executor.submit(run_jmeter_script, jmx) for jmx in jmx_files] 9 results = [f.result() for f in futures] 10
2.2 日志清理
1# 定期清理旧日志(保留最近30天) 2find /home/your-user/cicd/test/logs -name "*.csv" -mtime +30 -delete 3find /home/your-user/cicd/test/testscript/logs -name "*.log" -mtime +30 -delete 4
3. 监控与告警
3.1 添加失败重试机制
1def run_jmeter_script_with_retry(jmx_file, max_retries=3): 2 """带重试的 JMeter 执行""" 3 for attempt in range(max_retries): 4 result_csv, duration = run_jmeter_script(jmx_file) 5 if result_csv: 6 return result_csv, duration 7 8 if attempt < max_retries - 1: 9 print(f"重试 {attempt + 1}/{max_retries}...") 10 time.sleep(5) 11 12 return None, None 13
3.2 添加失败率告警
1def check_alert(results): 2 """检查是否需要告警""" 3 total_failed = sum([r['analysis']['failed'] for r in results if r['analysis']]) 4 total_requests = sum([r['analysis']['total'] for r in results if r['analysis']]) 5 6 fail_rate = total_failed / total_requests if total_requests > 0 else 0 7 8 # 失败率超过10%时特殊提醒 9 if fail_rate > 0.1: 10 send_alert_message(f"⚠️ 测试失败率过高:{fail_rate*100:.1f}%") 11
4. 目录规范
1project/ 2├── config.py # 配置文件(加入 .gitignore) 3├── config.example.py # 配置模板(提交到 git) 4├── jmeter_automation.py # 主程序 5├── clean_jmx.py # 工具脚本 6├── requirements.txt # Python 依赖 7├── README.md # 说明文档 8├── test/ 9│ ├── testscript/ # 测试脚本 10│ └── logs/ # 测试结果 11└── docs/ # 文档目录 12 └── 使用指南.md 13
5. JMX 文件管理
5.1 命名规范
1建议格式:{项目名}_{模块}_{测试类型}.jmx 2 3示例: 4- ProjectA_Login_API.jmx 5- ProjectA_Payment_Performance.jmx 6- ProjectB_Search_Stress.jmx 7
5.2 版本控制
1# 将 JMX 文件纳入 Git 管理 2git add test/testscript/*.jmx 3git commit -m "feat: 新增支付接口测试脚本" 4
总结
通过本指南,你已经学会了:
✅ 搭建 JMeter 自动化测试环境
✅ 配置飞书机器人实现消息通知
✅ 编写 Python 脚本批量执行测试
✅ 分析测试结果并生成报告
✅ 处理常见问题和故障排查
下一步建议
- 集成 CI/CD:将脚本集成到 Jenkins、GitLab CI 等平台
- 增强报告:添加趋势分析、图表展示
- 多渠道通知:支持钉钉、企业微信、邮件等
- Web 界面:开发 Web 控制台,可视化管理测试
参考资料
如果本文对你有帮助,欢迎点赞、收藏、转发!
《JMeter 自动化测试 + 飞书通知完整指南》 是转载文章,点击查看原文。
