测试基础 Python 操作 Jmeter 探索:pymeter 实操指南

花菜 · 2023年12月13日 · 最后由 Halo 回复于 2024年10月24日 · 6765 次阅读

1、背景

最近在技术群里面讨论到使用 python 操作 jmeter 的话题

有人提到了 subprocess 启动命令行来操作 jmeter,也有人提到了 jmeterapi,另外也有人提到了 pymeter

除了这些,实际上我之前也基于 docker+subprocess 来操作 jmeter 的项目

jmeterapi 这个库年久失修,就不想搞它了,下面跟我一起试试 pymeter 吧

image.png

image.png

2、环境准备

直接参考项目的说明即可
image.png

3、Jmeter 测试

3.1 写测试用例

使用方法比较简单,设置 GUI 类似,只是前后顺序不相同:

  • 创建线程组
  • 把 sample,断言,抽取等配置加入线程组
  • 创建报告收集器
  • 把线程组和报告收集器加入测试计划
  • 运行测试计划
# 省略 import

class TestTestPlanClass(TestCase):
    def test_1(self: Any) -> None:
        # 创建一个JsonExtractor对象,参数分别是"variable"和"args.var"
        json_extractor: JsonExtractor = JsonExtractor("variable", "args.var")

        # 创建一个均匀随机计时器,时间间隔在1000至2000毫秒之间
        timer: UniformRandomTimer = UniformRandomTimer(1000, 2000)

        ra: ResponseAssertion = ResponseAssertion.contains_substrings("var")
        # 创建一个HttpSampler对象,用于发送HTTP请求并记录响应
        http_sampler: HttpSampler = HttpSampler(
            "Echo",
            "http://119.91.147.215:18080/get?var=${__Random(0,10)}",
            timer,
            json_extractor,
            ra,
        )

        # 创建一个DummySampler对象,仅用于模拟一些操作,不实际执行任何网络请求
        dummy_sampler: DummySampler = DummySampler("dummy ${variable}", "hi dummy")

        # 创建一个线程组,其中包含10个线程,每个线程的运行时间为1秒,整个线程组的持续时间为60秒
        tg: ThreadGroupWithRampUpAndHold = ThreadGroupWithRampUpAndHold(
            100, 3, 60, http_sampler, dummy_sampler, name="Some Name"
        )

        # 创建一个HTML报告生成器
        html_reporter: HtmlReporter = HtmlReporter()

        # 创建一个测试计划,其中包含tg线程组和html_reporter报告生成器
        tp: TestPlan = TestPlan(tg, html_reporter)

        # 运行测试计划,返回统计数据
        stats = tp.run()

        # 打印测试的统计數據
        print(
            f"duration= {stats.duration_milliseconds}",
            f"mean= {stats.sample_time_mean_milliseconds}",
            f"min= {stats.sample_time_min_milliseconds}",
            f"median= {stats.sample_time_median_milliseconds}",
            f"90p= {stats.sample_time_90_percentile_milliseconds}",
            f"95p= {stats.sample_time_95_percentile_milliseconds}",
            f"99p= {stats.sample_time_99_percentile_milliseconds}",
            f"max= {stats.sample_time_max_milliseconds}",
            sep="\t",
        )

        # 断言99%分位数的样本时间小于2000毫秒
        self.assertLess(stats.sample_time_99_percentile_milliseconds, 30)

3.2 运行和收集结果

3.2.1 pycharm 启动

如果你使用的 PyCharm,会自动识别

image.png

3.2.2 命令行启动

# rikasai @ huacai-mbp in ~/code/python/pymeter-demo [22:23:38] C:1
$ python main.py
 +    579 in 00:00:07 =   86.2/s Avg:   139 Min:     9 Max:   500 Err:     0 (0.00%) Active: 100 Started: 100 Finished: 0
 +   3964 in 00:00:30 =  131.9/s Avg:   142 Min:     8 Max:   500 Err:     0 (0.00%) Active: 100 Started: 100 Finished: 0
 =   4543 in 00:00:37 =  123.6/s Avg:   142 Min:     8 Max:   500 Err:     0 (0.00%)
duration= 64265 mean= 144       min= 8  median= 54      90p= 404        95p= 451        99p= 491        max= 500
F +      7 in 00:00:03 =    2.1/s Avg:   864 Min:   225 Max:   977 Err:     0 (0.00%) Active: 6 Started: 6 Finished: 0
duration= 14276 mean= 323       min= 223        median= 230     90p= 960        95p= 973        99p= 1012       max= 1207
.
======================================================================
FAIL: test_1 (__main__.TestTestPlanClass)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/rikasai/code/python/pymeter-demo/main.py", line 67, in test_1
    self.assertLess(stats.sample_time_99_percentile_milliseconds, 30)
AssertionError: 491 not less than 30

----------------------------------------------------------------------
Ran 2 tests in 79.631s

FAILED (failures=1)
(pymeter-demo) 

需要注意的是,这里断言失败,是 unittest 断言失败,这个数据并不会在 jmeter 报告中体现

3.2.3 查看报告

报告会自动生成在 output 文件夹下面,一个 test 函数对应一份报告

使用浏览器打开 index.html 就能看到完整的报告

image.png

image.png

image.png

image.png

4、总结

  • python 结合 jmeter-dsl 的特性,使用起来很方便
  • 常用的部分功能(线程组,部分断言,报告)已经支持
  • 目前整体完成度还是偏低,插件,复杂的断言,各种 sample 还未支持

5、参考链接:

共收到 14 条回复 时间 点赞
花菜 #16 · 2023年12月13日 Author

欢迎留言和我交流哦

没想明白什么场景下会用到这个工具。一般都是生成好 JMX,然后丢给 Jmeter 去跑就好了呀

CKL的思考 回复

大概就是不想通过界面的方式去生成 jmeter,适合熟悉 py + jmeter,但不喜欢界面 +beanshell 的人

CKL的思考 回复

像我们这种搭建分布式压测机的公司,如果自己的电脑特别卡,就需要找个性能好的 linux 或 win 机的远程机器去跑,远程的时候,带 gui 和不带 gui 的系统,使用的卡顿感差异很大,更倾向于使用非 GUI 的方式去执行,这个就是一个不错的方案之一

simiko 回复

jmeter 也支持不带 gui 的运行,为什么会有这个想法呢

simiko 回复

Jmeter 也支持的啊,非 GUI 模式。这种方式严重依赖工具提供的功能,文章也说了很多 sample 还不支持。所以没想明白真实的应用场景是什么

花菜 回复

从技术的角度没毛病~~但是组内人要是怎么玩,是要挨骂的😀

我的第一感觉就是多此一举,画蛇添足,舍近求远,脱裤子放屁.

CKL的思考 回复

这个我就不知道了,我没有用过 jmeter 的非 GUI 模式呢~但是我如果遇到需要远程的,使用 linux 系统的,我应该会优先使用楼上的这种,或者 locust 的~

Nice,Mark 一下

花菜 #11 · 2023年12月14日 Author
CKL的思考 回复

这个是 pymeter 主页的说明,大概这些点:

  • 解决 jmeter 升级麻烦
  • 分享代码不方便
  • 不依赖 Jmeter GUI 编辑器

闲的蛋疼 搞一搞😁

13楼 已删除

搞这个,真是相当的闲呀

人家这么做有很多好处,可以搞成 web server 形式,做个压测平台

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册