JMeter 自动化测试 + 飞书通知完整指南

JMeter 自动化测试 + 飞书通知完整指南

从零开始搭建 JMeter 自动化测试系统,并通过飞书机器人实时推送测试报告

📖 目录


项目简介

背景

在持续集成/持续部署(CI/CD)流程中,自动化测试是保证代码质量的重要环节。本项目实现了:

  • 自动化执行:批量运行 JMeter 测试脚本
  • 智能分析:自动统计成功率、响应时间、失败详情
  • 实时通知:测试完成后立即推送飞书消息
  • 可视化报告:美观的飞书卡片样式报告

技术栈

  • 测试工具:Apache JMeter 5.6.3
  • 开发语言:Python 3.7+
  • 依赖库:pandas、requests
  • 通知渠道:飞书自定义机器人

效果展示

复制代码
📊 测试执行总览
🎉 执行状态:全部通过
📈 测试脚本:3 个 (成功执行: 3个, 执行失败: 0个)
🎯 接口统计:总计 150个, 成功 148个, 失败 2个
📊 整体成功率:98.7%
⏱️ 总耗时:5分32秒

系统架构

架构图

复制代码
┌─────────────────┐
│  JMeter 脚本    │
│   (.jmx 文件)   │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│  Python 调度器  │
│  批量执行测试   │
└────────┬────────┘
         │
         ├──► 1. 执行 JMeter 命令
         ├──► 2. 收集 CSV 结果
         ├──► 3. 分析测试数据
         └──► 4. 生成飞书报告
                      │
                      ▼
              ┌──────────────┐
              │  飞书机器人  │
              │  推送通知    │
              └──────────────┘

工作流程

  1. 扫描测试脚本 :自动发现指定目录下的所有 .jmx 文件
  2. 顺序执行测试:调用 JMeter 命令行逐个执行测试
  3. 结果收集分析:读取 CSV 结果文件,统计成功率、响应时间等
  4. 生成测试报告:汇总所有测试结果,格式化为 Markdown
  5. 发送飞书通知:通过 Webhook 推送卡片样式的报告

环境准备

硬件要求

  • 操作系统:Linux(推荐 CentOS 7+ / Ubuntu 18.04+)
  • 内存:至少 2GB
  • 磁盘:至少 5GB 可用空间

软件依赖

软件 版本要求 说明
Python 3.7+ 运行调度脚本
JMeter 5.6.2+ 执行性能测试
Java 8+ JMeter 运行依赖

配置参数说明

1. 飞书机器人配置

1.1 创建飞书自定义机器人

步骤:

  1. 打开飞书,进入目标群聊
  2. 点击右上角 「设置」「群机器人」
  3. 选择 「添加机器人」「自定义机器人」
  4. 填写机器人信息:
    • 名称JMeter 测试报告
    • 描述自动推送接口测试结果
  5. 安全设置 :勾选 「签名校验」
  6. 点击 「完成」,获取以下信息:

获取到的配置:

python 复制代码
# Webhook URL(示例,实际请替换为你的)
webhook = "https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

# 签名密钥 Secret(示例,实际请替换为你的)
secret = "YourSecretKeyHere123456"
1.2 参数获取位置
参数 获取方式 示例值
webhook 创建机器人后显示的 Webhook 地址 https://open.feishu.cn/open-apis/bot/v2/hook/xxx...
secret 启用签名校验后显示的密钥 YourSecretKeyHere123456

注意事项:

  • ⚠️ 请妥善保管 webhooksecret,避免泄露
  • ⚠️ 建议使用环境变量或配置文件存储,不要硬编码在代码中
  • ⚠️ 每个机器人的配置是唯一的,不同群需要创建不同的机器人

2. JMeter 配置

2.1 JMeter 安装路径

Linux 安装步骤:

bash 复制代码
# 1. 下载 JMeter(使用国内镜像加速)
cd /home/your-user
wget https://mirrors.tuna.tsinghua.edu.cn/apache/jmeter/binaries/apache-jmeter-5.6.3.tgz

# 2. 解压
tar -xzf apache-jmeter-5.6.3.tgz

# 3. 验证安装
/home/your-user/apache-jmeter-5.6.3/bin/jmeter -v

配置参数:

python 复制代码
# JMeter 可执行文件的完整路径
JMETER_BIN = "/home/your-user/apache-jmeter-5.6.3/bin/jmeter"
2.2 如何获取 JMeter 路径
bash 复制代码
# 方法1:使用 which 命令(如果已加入 PATH)
which jmeter

# 方法2:使用 find 命令查找
find /home -name "jmeter" -type f 2>/dev/null

# 方法3:查看安装目录
ls -la /home/your-user/apache-jmeter-*/bin/jmeter

3. 目录结构配置

3.1 推荐的目录结构
复制代码
/home/your-user/cicd/
├── test/
│   ├── testscript/          # 存放 .jmx 测试脚本
│   │   ├── test_api1.jmx
│   │   ├── test_api2.jmx
│   │   └── logs/            # JMeter 执行日志
│   └── logs/                # CSV 测试结果
├── jmeter_automation.py        # Python 主程序
└── clean_jmx.py             # JMX 文件清理工具
3.2 目录配置参数
python 复制代码
# 测试脚本存放目录
TEST_SCRIPT_DIR = "/home/your-user/cicd/test/testscript"

# CSV 结果文件输出目录
CSV_LOG_DIR = "/home/your-user/cicd/test/logs"

# JMeter 执行日志目录
JMETER_LOG_DIR = "/home/your-user/cicd/test/testscript/logs"
3.3 创建目录结构
bash 复制代码
# 创建所需目录
mkdir -p /home/your-user/cicd/test/testscript
mkdir -p /home/your-user/cicd/test/logs
mkdir -p /home/your-user/cicd/test/testscript/logs

# 设置权限
chmod -R 755 /home/your-user/cicd

4. 完整配置清单

创建配置文件 config.py

python 复制代码
# -*- coding: utf-8 -*-
"""
JMeter 自动化测试配置文件
请根据实际环境修改以下配置
"""

# ==================== 飞书机器人配置 ====================
# 获取方式:飞书群聊 → 设置 → 群机器人 → 添加自定义机器人
FEISHU_WEBHOOK = "https://open.feishu.cn/open-apis/bot/v2/hook/YOUR_WEBHOOK_ID"
FEISHU_SECRET = "YOUR_SECRET_KEY"

# ==================== JMeter 配置 ====================
# JMeter 可执行文件路径
# 获取方式:执行 'which jmeter' 或 'find /home -name jmeter'
JMETER_BIN = "/home/your-user/apache-jmeter-5.6.3/bin/jmeter"

# ==================== 目录配置 ====================
# 测试脚本目录(存放 .jmx 文件)
TEST_SCRIPT_DIR = "/home/your-user/cicd/test/testscript"

# CSV 结果输出目录
CSV_LOG_DIR = "/home/your-user/cicd/test/logs"

# JMeter 日志目录
JMETER_LOG_DIR = "/home/your-user/cicd/test/testscript/logs"

# ==================== 执行配置 ====================
# 单个测试超时时间(秒)
TEST_TIMEOUT = 600  # 10分钟

# 是否使用飞书卡片样式
USE_CARD_STYLE = True

配置验证检查清单:

bash 复制代码
# 检查 JMeter 是否可用
/home/your-user/apache-jmeter-5.6.3/bin/jmeter -v

# 检查目录是否存在
ls -la /home/your-user/cicd/test/testscript

# 检查 Python 依赖
python3 -c "import pandas, requests; print('依赖检查通过')"

# 测试飞书 Webhook(可选)
curl -X POST "$FEISHU_WEBHOOK" \
  -H 'Content-Type: application/json' \
  -d '{"msg_type":"text","content":{"text":"测试消息"}}'

实施步骤

第一步:环境安装

1.1 安装 Python 依赖
bash 复制代码
# 安装 pandas 和 requests
pip3 install pandas requests

# 或使用 requirements.txt
cat > requirements.txt <<EOF
pandas>=1.3.0
requests>=2.25.0
EOF

pip3 install -r requirements.txt
1.2 安装 JMeter
bash 复制代码
# 使用清华镜像下载(速度快)
cd /home/your-user
wget https://mirrors.tuna.tsinghua.edu.cn/apache/jmeter/binaries/apache-jmeter-5.6.3.tgz

# 解压
tar -xzf apache-jmeter-5.6.3.tgz

# 验证
./apache-jmeter-5.6.3/bin/jmeter -v

第二步:创建飞书机器人

2.1 操作步骤
  1. 打开飞书客户端
  2. 进入要接收通知的群聊
  3. 点击群设置 → 群机器人 → 添加机器人
  4. 选择"自定义机器人"
  5. 配置:
    • 名称:JMeter 自动化测试报告
    • 启用签名校验:✅
  6. 保存 Webhook URL 和 Secret
2.2 验证机器人
bash 复制代码
# 发送测试消息
WEBHOOK="你的webhook地址"
SECRET="你的secret"
TIMESTAMP=$(date +%s)

# 生成签名
SIGN=$(echo -ne "${TIMESTAMP}\n${SECRET}" | openssl dgst -sha256 -hmac "" -binary | base64)

# 发送消息
curl -X POST "$WEBHOOK" \
  -H 'Content-Type: application/json' \
  -d "{
    \"timestamp\": $TIMESTAMP,
    \"sign\": \"$SIGN\",
    \"msg_type\": \"text\",
    \"content\": {\"text\": \"✅ 飞书机器人配置成功!\"}
  }"

第三步:准备测试脚本

3.1 创建目录结构
bash 复制代码
mkdir -p /home/your-user/cicd/test/testscript
mkdir -p /home/your-user/cicd/test/logs
mkdir -p /home/your-user/cicd/test/testscript/logs
3.2 上传 JMX 文件
bash 复制代码
# 从本地上传(在 Windows 执行)
scp your-test.jmx user@server:/home/your-user/cicd/test/testscript/
3.3 清理 JMX 文件中的第三方插件(重要!)

问题说明:

JMeter 脚本可能包含第三方可视化插件(如 kg.apc.jmeter.vizualizers.*),这些插件:

  • 只在 GUI 模式下有用
  • 命令行模式不需要
  • 如果缺少插件会导致执行失败

解决方案:清理可视化组件

bash 复制代码
# 方法1:使用 sed 命令清理
cd /home/your-user/cicd/test/testscript
cp your-test.jmx your-test.jmx.bak  # 备份

sed -i '/<kg\.apc\.jmeter\.vizualizers/,/<\/kg\.apc\.jmeter\.vizualizers/d' your-test.jmx

# 方法2:使用 Python 清理脚本(推荐)
python3 clean_jmx.py your-test.jmx

验证清理效果:

bash 复制代码
# 检查是否还有第三方插件引用
grep "kg.apc.jmeter" your-test.jmx

# 如果无输出,说明清理成功

# 测试运行
/home/your-user/apache-jmeter-5.6.3/bin/jmeter \
  -n -t your-test.jmx -l test.csv -j test.log

第四步:部署 Python 脚本

4.1 上传脚本
bash 复制代码
# 上传主程序
scp jmeter_automation.py user@server:/home/your-user/cicd/

# 上传配置文件
scp config.py user@server:/home/your-user/cicd/
4.2 修改配置
bash 复制代码
# 编辑配置文件
vim /home/your-user/cicd/config.py

# 修改以下配置:
# 1. FEISHU_WEBHOOK - 改为你的 webhook 地址
# 2. FEISHU_SECRET - 改为你的 secret
# 3. JMETER_BIN - 改为你的 JMeter 路径
# 4. TEST_SCRIPT_DIR - 改为你的脚本目录

第五步:运行测试

5.1 手动执行
bash 复制代码
cd /home/your-user/cicd
python3 jmeter_automation.py

预期输出示例:

复制代码
🚀 JMeter 自动化测试开始
==================================================
📋 找到 3 个测试脚本,开始批量执行...

[1/3] 正在处理:test_api_login.jmx
🚀 开始执行:test_api_login.jmx
✅ 完成执行:test_api_login.jmx,耗时:1分23秒

[2/3] 正在处理:test_api_search.jmx
🚀 开始执行:test_api_search.jmx
✅ 完成执行:test_api_search.jmx,耗时:2分15秒

==================================================
📊 所有测试执行完成,生成报告...
📤 正在发送报告到飞书...
✅ 飞书报告发送成功!

🎉 所有任务完成!

5.2 设置定时任务(使用 crontab)

什么是 Crontab?

Crontab 是 Linux 系统的定时任务工具,可以让脚本在指定时间自动运行。

操作步骤:

bash 复制代码
# 1. 编辑定时任务
crontab -e

首次使用会让你选择编辑器:

复制代码
Select an editor.  To change later, run 'select-editor'.
  1. /bin/nano        <---- 最简单,推荐新手
  2. /usr/bin/vim.basic
  3. /usr/bin/vim.tiny

Choose 1-3 [1]: 1  # 输入 1 选择 nano 编辑器

添加定时任务:

在打开的编辑器中,添加以下内容(根据需求选择):

bash 复制代码
# ==================== 定时任务示例 ====================

# 每天上午 9 点执行测试
0 9 * * * /usr/bin/python3 /home/your-user/cicd/jmeter_automation.py >> /home/your-user/cicd/cron.log 2>&1

# 每天凌晨 2 点执行测试
0 2 * * * /usr/bin/python3 /home/your-user/cicd/jmeter_automation.py >> /home/your-user/cicd/cron.log 2>&1

# 每周一上午 9 点执行
0 9 * * 1 /usr/bin/python3 /home/your-user/cicd/jmeter_automation.py >> /home/your-user/cicd/cron.log 2>&1

# 每小时执行一次
0 * * * * /usr/bin/python3 /home/your-user/cicd/jmeter_automation.py >> /home/your-user/cicd/cron.log 2>&1

# 工作日(周一到周五)上午 10 点执行
0 10 * * 1-5 /usr/bin/python3 /home/your-user/cicd/jmeter_automation.py >> /home/your-user/cicd/cron.log 2>&1

Crontab 时间格式说明:

复制代码
 ┌───────────── 分钟 (0 - 59)
 │ ┌───────────── 小时 (0 - 23)
 │ │ ┌───────────── 日期 (1 - 31)
 │ │ │ ┌───────────── 月份 (1 - 12)
 │ │ │ │ ┌───────────── 星期 (0 - 7, 0 和 7 都表示周日)
 │ │ │ │ │
 * * * * * 要执行的命令

常用时间表达式:

表达式 说明 示例
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 编辑器(推荐新手)

复制代码
1. 添加完定时任务后
2. 按 Ctrl + X(退出)
3. 提示 "Save modified buffer?" 时,按 Y(保存)
4. 提示 "File Name to Write" 时,直接按 Enter(确认)
5. 看到 "crontab: installing new crontab" 表示成功

方式二:使用 vim 编辑器

复制代码
1. 添加完定时任务后
2. 按 Esc 键(进入命令模式)
3. 输入 :wq 然后按 Enter(保存并退出)

# 不保存退出
Esc → :q! → Enter

快捷键总结:

编辑器 保存并退出 不保存退出
nano Ctrl + XYEnter Ctrl + XN
vim Esc:wqEnter Esc:q!Enter

验证定时任务:

bash 复制代码
# 查看当前用户的定时任务
crontab -l

# 查看 crontab 服务状态
systemctl status cron       # Ubuntu/Debian
systemctl status crond      # CentOS/RHEL

# 查看 crontab 执行日志
tail -f /var/log/cron        # CentOS/RHEL
tail -f /var/log/syslog      # Ubuntu/Debian

# 查看自定义的执行日志
tail -f /home/your-user/cicd/cron.log

常用 crontab 命令:

bash 复制代码
crontab -e      # 编辑定时任务
crontab -l      # 列出所有定时任务
crontab -r      # 删除所有定时任务(谨慎使用!)
crontab -u user -e   # 编辑指定用户的定时任务(需要 root 权限)

测试定时任务(可选):

如果想立即测试定时任务是否正常工作,可以临时设置一个1分钟后执行的任务:

bash 复制代码
# 1. 查看当前时间
date

# 假设现在是 14:30,那么设置 14:31 执行
crontab -e

# 添加(1分钟后执行)
31 14 * * * /usr/bin/python3 /home/your-user/cicd/jmeter_automation.py >> /home/your-user/cicd/test.log 2>&1

# 2. 等待 1 分钟后查看日志
tail -f /home/your-user/cicd/test.log

# 3. 测试成功后,删除测试任务
crontab -e  # 删除刚才添加的测试行

注意事项:

⚠️ 路径必须使用绝对路径

bash 复制代码
# ✅ 正确
0 9 * * * /usr/bin/python3 /home/your-user/cicd/jmeter_automation.py

# ❌ 错误(相对路径在 crontab 中不工作)
0 9 * * * python3 jmeter_automation.py

⚠️ 指定完整的 Python 解释器路径

bash 复制代码
# 查找 Python3 的完整路径
which python3
# 输出:/usr/bin/python3

# 在 crontab 中使用完整路径
/usr/bin/python3 /path/to/script.py

⚠️ 重定向日志输出

bash 复制代码
# >> cron.log 2>&1 的含义:
# >> cron.log        - 将标准输出追加到 cron.log
# 2>&1              - 将错误输出也重定向到标准输出(即同一个文件)

# 这样可以在日志文件中看到所有输出和错误信息

⚠️ 时区问题

bash 复制代码
# 检查服务器时区
date
timedatectl

# 如果时区不对,修改时区(以中国为例)
sudo timedatectl set-timezone Asia/Shanghai

代码实现

核心代码结构

python 复制代码
# -*- coding: utf-8 -*-
import hashlib, base64, hmac, requests
import pandas as pd
import time, os, subprocess, json
from datetime import datetime

# ==================== 配置部分 ====================
# 从配置文件导入或直接定义
from config import (
    FEISHU_WEBHOOK,
    FEISHU_SECRET,
    JMETER_BIN,
    TEST_SCRIPT_DIR,
    CSV_LOG_DIR,
    JMETER_LOG_DIR,
    TEST_TIMEOUT,
    USE_CARD_STYLE
)

# ==================== 飞书签名生成 ====================
def gen_sign(timestamp, secret):
    """生成飞书机器人签名"""
    string_to_sign = f'{timestamp}\n{secret}'
    hmac_code = hmac.new(
        string_to_sign.encode(),
        digestmod=hashlib.sha256
    ).digest()
    return base64.b64encode(hmac_code).decode()

# ==================== 发送飞书消息 ====================
def send_message(timestamp, sign_id, content_blocks, use_card_style=False):
    """发送消息到飞书"""
    url = webhook
    headers = {'Content-Type': 'application/json'}

    if use_card_style:
        # 使用卡片样式
        # 将content_blocks转换为markdown文本
        markdown_content = ""
        for block in content_blocks:
            if block and len(block) > 0 and "text" in block[0]:
                text = block[0]["text"]
                if text.strip():  # 只添加非空文本
                    markdown_content += text + "\n\n"

        data = {
            "timestamp": timestamp,
            "sign": sign_id,
            "msg_type": "interactive",
            "card": {
                "schema": "2.0",
                "config": {
                    "update_multi": True,
                    "style": {
                        "text_size": {
                            "normal_v2": {
                                "default": "normal",
                                "pc": "normal",
                                "mobile": "heading"
                            }
                        }
                    }
                },
                "body": {
                    "direction": "vertical",
                    "padding": "16px 16px 16px 16px",
                    "elements": [
                        {
                            "tag": "markdown",
                            "content": markdown_content,
                            "text_align": "left",
                            "text_size": "normal_v2",
                            "margin": "0px 0px 0px 0px"
                        }
                    ]
                },
                "header": {
                    "title": {
                        "tag": "plain_text",
                        "content": "🧪 JMeter 自动化测试报告"
                    },
                    "subtitle": {
                        "tag": "plain_text",
                        "content": f"执行时间:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
                    },
                    "template": "blue",
                    "padding": "12px 12px 12px 12px"
                }
            }
        }
    else:
        # 使用原来的post样式
        data = {
            "timestamp": timestamp,
            "sign": sign_id,
            "msg_type": "post",
            "content": {
                "post": {
                    "zh_cn": {
                        "title": "🧪 JMeter 自动化测试报告",
                        "content": content_blocks
                    }
                }
            }
        }

    # 打印调试信息
    print("发送的数据结构:")
    print(json.dumps(data, ensure_ascii=False, indent=2))

    response = requests.post(url, headers=headers, json=data)
    return response.json()

# ==================== 执行 JMeter 测试 ====================
def run_jmeter_script(jmx_file):
    """运行 JMeter 脚本"""
    start_time = time.time()
    current_time = datetime.now().strftime("%Y_%m_%d_%H_%M_%S")
    name = os.path.basename(jmx_file)

    result_csv = f"{CSV_LOG_DIR}/{name}_{current_time}.csv"
    result_log = f"{JMETER_LOG_DIR}/{name}_{current_time}.log"

    # 创建日志目录
    os.makedirs(os.path.dirname(result_csv), exist_ok=True)
    os.makedirs(os.path.dirname(result_log), exist_ok=True)

    cmd = [
        JMETER_BIN,
        "-n", "-t", jmx_file,
        "-l", result_csv,
        "-j", result_log
    ]

    print(f"🚀 开始执行:{name}")
    try:
        subprocess.run(cmd, check=True, timeout=TEST_TIMEOUT)
        duration = time.time() - start_time
        print(f"✅ 完成执行:{name},耗时:{format_duration(duration)}")
        return result_csv, duration
    except subprocess.TimeoutExpired:
        print(f"⏰ 执行超时:{name}")
        return None, None
    except subprocess.CalledProcessError as e:
        print(f"❌ 执行失败:{name},错误:{e}")
        return None, None

# ==================== 分析测试结果 ====================
def analyze_csv_results(csv_file):
    """分析 CSV 结果文件"""
    try:
        df = pd.read_csv(csv_file)

        total_requests = len(df)
        success_requests = len(df[df['success'] == True])
        failed_requests = len(df[df['success'] == False])
        success_rate = (success_requests / total_requests * 100) if total_requests > 0 else 0
        avg_response_time = df['elapsed'].mean() if 'elapsed' in df.columns else 0

        # 获取失败详情
        failed_details = []
        if failed_requests > 0:
            failed = df[df["success"] == False]
            for _, row in failed.iterrows():
                failed_details.append({
                    'label': str(row.get("label")),
                    'responseCode': str(row.get("responseCode")),
                    'failureMessage': str(row.get("failureMessage")),
                    'url': str(row.get("URL"))
                })

        return {
            'total': total_requests,
            'success': success_requests,
            'failed': failed_requests,
            'success_rate': success_rate,
            'avg_response_time': avg_response_time,
            'failed_details': failed_details
        }
    except Exception as e:
        print(f"分析 CSV 文件失败:{str(e)}")
        return None

# ==================== 主函数 ====================
def main():
    """主函数"""
    print("🚀 JMeter 自动化测试开始")
    start_time = time.time()

    # 获取所有 JMX 文件
    jmx_files = sorted([
        os.path.join(TEST_SCRIPT_DIR, f)
        for f in os.listdir(TEST_SCRIPT_DIR)
        if f.endswith(".jmx")
    ])

    if not jmx_files:
        print(f"⚠️ 警告:在 {TEST_SCRIPT_DIR} 中没有找到任何 .jmx 文件")
        return

    print(f"📋 找到 {len(jmx_files)} 个测试脚本")

    # 执行所有测试
    results = []
    for jmx in jmx_files:
        result_csv, duration = run_jmeter_script(jmx)
        analysis = analyze_csv_results(result_csv) if result_csv else None

        results.append({
            'name': os.path.basename(jmx),
            'duration': duration or 0,
            'analysis': analysis,
            'status': 'success' if analysis else 'failed'
        })

    # 生成并发送报告
    # ... 详见完整代码

    print("🎉 所有任务完成!")

if __name__ == "__main__":
    main()

常见问题

1. JMeter 执行失败:找不到插件

错误信息:

复制代码
CannotResolveClassException: kg.apc.jmeter.vizualizers.CorrectedResultCollector

原因: JMX 文件中包含第三方可视化插件

解决方案:

bash 复制代码
# 清理 JMX 文件中的可视化组件
sed -i '/<kg\.apc\.jmeter\.vizualizers/,/<\/kg\.apc\.jmeter\.vizualizers/d' your-test.jmx

2. 飞书消息发送失败

错误代码: code: 19021

原因: 签名验证失败

解决方案:

  1. 检查 secret 是否正确
  2. 检查时间戳是否为当前时间(秒级)
  3. 检查签名生成算法是否正确
python 复制代码
# 正确的签名生成
timestamp = int(time.time())  # 必须是整数秒
string_to_sign = f'{timestamp}\n{secret}'
hmac_code = hmac.new(string_to_sign.encode(), digestmod=hashlib.sha256).digest()
sign = base64.b64encode(hmac_code).decode()

3. CSV 文件无法解析

错误信息: KeyError: 'success'

原因: JMeter 配置未正确输出结果

解决方案:

确保 JMeter 脚本中包含"简单数据写入器"或正确的监听器配置:

xml 复制代码
<ResultCollector guiclass="SimpleDataWriter" testclass="ResultCollector">
  <objProp>
    <value class="SampleSaveConfiguration">
      <time>true</time>
      <latency>true</latency>
      <success>true</success>
      <label>true</label>
      <code>true</code>
      <message>true</message>
      <responseData>false</responseData>
    </value>
  </objProp>
</ResultCollector>

4. 权限问题

错误信息: Permission denied

解决方案:

bash 复制代码
# 给脚本执行权限
chmod +x jmeter_automation.py

# 给目录写权限
chmod -R 755 /home/your-user/cicd

最佳实践

1. 安全性建议

1.1 敏感信息管理

不推荐:硬编码

python 复制代码
webhook = "https://open.feishu.cn/open-apis/bot/v2/hook/xxx"  # ❌
secret = "my-secret-key"  # ❌

推荐:使用环境变量

python 复制代码
import os

webhook = os.getenv('FEISHU_WEBHOOK')
secret = os.getenv('FEISHU_SECRET')
bash 复制代码
# 设置环境变量
export FEISHU_WEBHOOK="https://open.feishu.cn/..."
export FEISHU_SECRET="your-secret"

# 或写入 .env 文件
echo 'FEISHU_WEBHOOK="https://..."' >> .env
echo 'FEISHU_SECRET="xxx"' >> .env

推荐:使用配置文件 + .gitignore

python 复制代码
# config.py (加入 .gitignore)
FEISHU_WEBHOOK = "..."
FEISHU_SECRET = "..."
bash 复制代码
# .gitignore
config.py
*.pyc
__pycache__/
1.2 Webhook 访问控制
  • 仅在受信任的服务器上部署
  • 定期轮换 Secret 密钥
  • 限制机器人权限(只读群聊信息)

2. 性能优化

2.1 并行执行测试(可选)
python 复制代码
from concurrent.futures import ThreadPoolExecutor

def main():
    jmx_files = [...]

    # 使用线程池并行执行(谨慎使用,可能导致资源竞争)
    with ThreadPoolExecutor(max_workers=3) as executor:
        futures = [executor.submit(run_jmeter_script, jmx) for jmx in jmx_files]
        results = [f.result() for f in futures]
2.2 日志清理
bash 复制代码
# 定期清理旧日志(保留最近30天)
find /home/your-user/cicd/test/logs -name "*.csv" -mtime +30 -delete
find /home/your-user/cicd/test/testscript/logs -name "*.log" -mtime +30 -delete

3. 监控与告警

3.1 添加失败重试机制
python 复制代码
def run_jmeter_script_with_retry(jmx_file, max_retries=3):
    """带重试的 JMeter 执行"""
    for attempt in range(max_retries):
        result_csv, duration = run_jmeter_script(jmx_file)
        if result_csv:
            return result_csv, duration

        if attempt < max_retries - 1:
            print(f"重试 {attempt + 1}/{max_retries}...")
            time.sleep(5)

    return None, None
3.2 添加失败率告警
python 复制代码
def check_alert(results):
    """检查是否需要告警"""
    total_failed = sum([r['analysis']['failed'] for r in results if r['analysis']])
    total_requests = sum([r['analysis']['total'] for r in results if r['analysis']])

    fail_rate = total_failed / total_requests if total_requests > 0 else 0

    # 失败率超过10%时特殊提醒
    if fail_rate > 0.1:
        send_alert_message(f"⚠️ 测试失败率过高:{fail_rate*100:.1f}%")

4. 目录规范

复制代码
project/
├── config.py              # 配置文件(加入 .gitignore)
├── config.example.py      # 配置模板(提交到 git)
├── jmeter_automation.py      # 主程序
├── clean_jmx.py           # 工具脚本
├── requirements.txt       # Python 依赖
├── README.md              # 说明文档
├── test/
│   ├── testscript/        # 测试脚本
│   └── logs/              # 测试结果
└── docs/                  # 文档目录
    └── 使用指南.md

5. JMX 文件管理

5.1 命名规范
复制代码
建议格式:{项目名}_{模块}_{测试类型}.jmx

示例:
- ProjectA_Login_API.jmx
- ProjectA_Payment_Performance.jmx
- ProjectB_Search_Stress.jmx
5.2 版本控制
bash 复制代码
# 将 JMX 文件纳入 Git 管理
git add test/testscript/*.jmx
git commit -m "feat: 新增支付接口测试脚本"

总结

通过本指南,你已经学会了:

✅ 搭建 JMeter 自动化测试环境

✅ 配置飞书机器人实现消息通知

✅ 编写 Python 脚本批量执行测试

✅ 分析测试结果并生成报告

✅ 处理常见问题和故障排查

下一步建议

  1. 集成 CI/CD:将脚本集成到 Jenkins、GitLab CI 等平台
  2. 增强报告:添加趋势分析、图表展示
  3. 多渠道通知:支持钉钉、企业微信、邮件等
  4. Web 界面:开发 Web 控制台,可视化管理测试

参考资料


如果本文对你有帮助,欢迎点赞、收藏、转发!

相关推荐
小小测试开发7 小时前
JMeter JSR223预处理程序高级用法:解锁自动化测试的灵活性上限
开发语言·jmeter·groovy
CesareCheung8 小时前
JMeter 进行 WebSocket 接口压测
python·websocket·jmeter
CesareCheung11 小时前
JMeter 使用分布式压测的原因
分布式·jmeter
玩泥巴的15 小时前
.NET项目中如何快速的集成飞书API
c#·.net·飞书
CesareCheung17 小时前
JMeter 分布式压测配置
分布式·jmeter
卖个几把萌1 天前
【09】JMeter插件管理下载
测试工具·jmeter
小小测试开发1 天前
JMeter高级用法全解析:从性能测试到自动化监控,解锁压测工具的隐藏实力
运维·jmeter·自动化
2501_939508642 天前
Tomcat服务器性能优化提升应用响应速度的关键策略
jmeter
卖个几把萌3 天前
【07】JMeter 将Swagger接口直接转为JMeter脚本
测试工具·jmeter