如何使用 Loadgen 来简化 HTTP API 请求的集成测试
引言
在编写 HTTP 服务的过程中,集成测试 1 是保证程序正确性的重要一环,如下图所示,其基本的流程就是不断向服务发起请求然后校验响应的状态和数据等:
为大量的 API 和用例编写测试是一件繁琐的工作,而 Loadgen 2 正是为了简化这一过程而设计的。
一个简单的测试
假定我们在 127.0.0.1:9100
端口监听了一个 Pizza 3 服务,现在我们通过如下配置来测试集合(collection)的创建:
# loadgen.yml
requests:- request:method: PUTurl: http://127.0.0.1:9100/test_create_document
然后运行 loadgen -config loadgen.yml
:
$ loadgen -config loadgen.yml__ ___ _ ___ ___ __ __/ / /___\/_\ / \/ _ \ /__\/\ \ \/ / // ///_\\ / /\ / /_\//_\ / \/ /
/ /__/ \_// _ \/ /_// /_\\//__/ /\ /
\____|___/\_/ \_/___,'\____/\__/\_\ \/[LOADGEN] A http load generator and testing suite.
[INF] warmup started
[INF] loadgen is up and running now.
[INF] [PUT] http://127.0.0.1:9100/test_create_document -
[INF] status: 200, error: <nil>, response: {"success":true,"collection":"test_create_document"}
[INF] warmup finished
...
为了便于阅读,笔者对程序输出进行了简化,实际会略有区别
可以看到,Loadgen 实际上帮我们做了类似这样的操作:
curl -XPUT http://127.0.0.1:9100/test_create_document
一些简单的测试
上述示例中我们只测试了创建单个集合,但是实际情况下短时间内会有许多请求涌入,对于创建大量的集合我们又该如何测试呢?
这里就需要用到变量 4 的概念:
# loadgen.yml
variables:- name: idtype: sequence
requests:- request:method: PUTurl: http://127.0.0.1:9100/test_create_document_$[[id]]
上述配置中,我们定义了一个名为 id
的变量,sequence
是一个特殊的类型——每次被读取时它的值会递增,因此 Loadgen 会不断发起类似这样的请求:
curl -XPUT http://127.0.0.1:9100/test_create_document_0
curl -XPUT http://127.0.0.1:9100/test_create_document_1
curl -XPUT http://127.0.0.1:9100/test_create_document_2
...
在 Pizza 的日志中也记录了这些请求:
$ pizza___ _____ __________ _/ _ \\_ \/ _ / _ / /_\/ /_)/ / /\/\// /\// / //_\\
/ ___/\/ /_ / //\/ //\/ _ \
\/ \____/ /____/____/\_/ \_/[PIZZA] The Next-Gen Real-Time Hybrid Search & AI-Native Innovation Engine.
[INFO] Collection test_create_document_0 created
[INFO] Collection test_create_document_1 created
[INFO] Collection test_create_document_2 created
...
不那么简单的测试
目前为止,我们只是不断的向一个服务“塞”大量的请求,但比起发起请求,我们常常更关心程序的响应是否符合预期,也就是说,响应需要满足我们定义的一些条件,这可以通过 Loadgen 提供的 断言 5 功能来实现:
# loadgen.yml
variables:- name: idtype: sequence
runner:# 检查返回值是否正常assert_error: true# 检查断言是否通过assert_invalid: true
requests:- request:method: PUTurl: http://127.0.0.1:9100/test_create_document_$[[id]]assert:equals:# 注意,这里我们故意设置了一个“不正常”的值,以迫使断言失败_ctx.response.body_json.success: false
在上述配置中,我们启用了 Loadgen 的检查,然后定义了一个会失败的断言:
equals
会校验给定路径_ctx.response.body_json.success
是否与期望值false
相等_ctx.response.body_json
表示 JSON 格式的响应体success
表示响应体中该字段对应的值,可以用path.to.nested.key
来访问嵌套的字段
也就是说,给定响应体 {"success":true,"collection":"test_create_document"}
,Loadgen 会检查 success
的值是否为 false
:
$ loadgen -debug -r 1 -d 3 -config loadgen.yml
#0 request, PUT http://127.0.0.1:9100/test_create_document_$[[id]], assertion failed, skiping subsequent requests
[WRN] '_ctx.response.body_json.success' is not equal to expected value: true
#0 request, PUT http://127.0.0.1:9100/test_create_document_$[[id]], assertion failed, skiping subsequent requests
[WRN] '_ctx.response.body_json.success' is not equal to expected value: true
#0 request, PUT http://127.0.0.1:9100/test_create_document_$[[id]], assertion failed, skiping subsequent requests
[WRN] '_ctx.response.body_json.success' is not equal to expected value: true
#0 request, PUT http://127.0.0.1:9100/test_create_document_$[[id]], assertion failed, skiping subsequent requests
[WRN] '_ctx.response.body_json.success' is not equal to expected value: true
上述命令我们使用了:
-debug
启用更详细的报错-r 1 -d 3
减少发起的请求数(1req/s
持续3s
)还有一个需要注意的细节是
... is not equal to expected value: true
,这里报告的是success
字段实际的值,而不是断言中定义的期望值。
可以看到,Loadgen 每次请求的断言都失败了,不过我们可以通过日志来快速定位出错的原因以便于调试。
更进一步的测试
现在我们创建了大量的空集合,是时候向其中添加一些文档(document)了,但是,一个首要解决的问题是,每次测试创建的集合名称是带有 $[[id]]
这个变量的,我们如何知道应该向哪个集合上传数据呢?一个可靠的解决方案是借助 Loadgen 的寄存器 6 功能:
# loadgen.yml
variables:- name: idtype: sequence
runner:assert_error: trueassert_invalid: true
requests:- request:method: PUTurl: http://127.0.0.1:9100/test_create_document_$[[id]]assert:equals:_ctx.response.body_json.success: trueregister:# 把响应体的 collection 字段赋值给 $[[collection]]- collection: _ctx.response.body_json.collection- request:method: POST# 在上个请求创建的集合里添加一个文档url: http://127.0.0.1:9100/$[[collection]]/_docbody: '{"hello": "world"}'assert:equals:_ctx.response.body_json.result: created
上述示例中,我们利用动态注册的变量记录了每次测试创建的集合以便于后续请求使用。
最后的优化
为了使我们的配置更加灵活和“便携”,我们可以用环境变量来替换一些硬编码的值:
# loadgen.yml
variables:- name: idtype: sequence
runner:assert_error: trueassert_invalid: true
requests:- request:method: PUT# 读取 PIZZA_SERVER 这个环境变量url: $[[env.PIZZA_SERVER]]/test_create_document_$[[id]]assert:equals:_ctx.response.body_json.success: trueregister:- collection: _ctx.response.body_json.collection- request:method: POSTurl: $[[env.PIZZA_SERVER]]/$[[collection]]/_docbody: '{"hello": "world"}'assert:equals:_ctx.response.body_json.result: created
这样就可以通过:
PIZZA_SERVER=http://127.0.0.1:9101 loadgen -config loadgen.yml
在不同的 Pizza 服务上运行测试。
https://en.wikipedia.org/wiki/Integration_testing ↩︎
https://www.infinilabs.com/docs/latest/gateway/getting-started/benchmark ↩︎
https://www.infinilabs.com/en/docs/latest/pizza ↩︎
https://www.infinilabs.com/docs/latest/gateway/getting-started/benchmark#变量的使用 ↩︎
https://www.infinilabs.com/docs/latest/gateway/getting-started/benchmark#返回值判断 ↩︎
https://www.infinilabs.com/docs/latest/gateway/getting-started/benchmark#动态变量注册 ↩︎
相关文章:

如何使用 Loadgen 来简化 HTTP API 请求的集成测试
引言 在编写 HTTP 服务的过程中,集成测试 1 是保证程序正确性的重要一环,如下图所示,其基本的流程就是不断向服务发起请求然后校验响应的状态和数据等: 为大量的 API 和用例编写测试是一件繁琐的工作,而 Loadgen 2 正…...

软件测试面试大家是不是一问到项目就不会了?
软件测试面试中,介绍做过的项目,可以说是必不可少的一道面试题了,对于面试的同学来说,该自己发挥呢? 把项目的所有功能噼里啪啦说一遍就完事了?当然不是,我们要搞清楚,面试官问这个…...

伐木猪小游戏
欢迎来到程序小院 伐木猪 玩法:控制小猪点击屏幕左右砍树,不能碰到树枝,考验手速与眼力,记录分数,快去挑战伐木吧^^。开始游戏https://www.ormcc.com/play/gameStart/199 html <script type"text/javascript…...

0007Java安卓程序设计-ssm基于Android的校园新闻管理系统
文章目录 **摘** **要**目 录开发环境 编程技术交流、源码分享、模板分享、网课教程 🐧裙:776871563 摘 要 网络的广泛应用给生活带来了十分的便利。所以把校园新闻管理与现在网络相结合,利用java技术建设校园新闻管理系统app,实…...

git增加右键菜单
有次不小心清理系统垃圾,把git右击菜单搞没了,下面是恢复方法 将下面代码存为.reg文件,双击后导出生效,注意,你安装的git必须是默认C盘的,如果换了地方要改下面注册表文件中相关的位置 Windows Registry …...

openGauss学习笔记-117 openGauss 数据库管理-设置数据库审计-查看审计结果
文章目录 openGauss学习笔记-117 openGauss 数据库管理-设置数据库审计-查看审计结果117.1 前提条件117.2 背景信息117.3 操作步骤 openGauss学习笔记-117 openGauss 数据库管理-设置数据库审计-查看审计结果 117.1 前提条件 审计功能总开关已开启。需要审计的审计项开关已开…...
学习代码20231106
解释代码:os.environ[“OMP_NUM_THREADS“] “1“ 这行代码涉及到 Python 的 os 模块和环境变量。它的作用是设置名为 “OMPNUMTHREADS” 的环境变量的值为 “1”。让我解释一下各部分的含义: 1.os.environ: 这是 Python 中的一个字典,包含…...

turtle绘制分形树-第10届蓝桥杯省赛Python真题精选
[导读]:超平老师的Scratch蓝桥杯真题解读系列在推出之后,受到了广大老师和家长的好评,非常感谢各位的认可和厚爱。作为回馈,超平老师计划推出《Python蓝桥杯真题解析100讲》,这是解读系列的第5讲。 turtle绘制分形树&…...
【大厂招聘试题】__硬件工程师_2021年“美团”校招
目录 匹配职位:硬件工程师 1.(多选题)单处理系统中,进程P1,P2,P3处于就绪队列,进程P4,P6处于等待队列,P5正占用处理器运行,以下对接下来的运行合理的分析是( ÿ…...
算法通关村第七关|黄金挑战|迭代实现二叉树的前、中、后序遍历
1.迭代实现前序遍历 public List<Integer> preOrderTraversal(TreeNode root) {List<Integer> res new ArrayList<Integer>();if (root null) {return res;}Deque<TreeNode> stack new LinkedList<TreeNode>();TreeNode node root;while (!…...

了解高防服务器的工作原理
在当今互联网时代,网络安全问题日益突出,各种网络攻击层出不穷。为了保护企业的网络安全,高防服务器应运而生。那么,你是否了解高防服务器的工作原理呢?下面就让我们一起来探索一下。 高防服务器是一种能够有效抵御各种网络攻击的…...

AVL树性质和实现
AVL树 AVL是两名俄罗斯数学家的名字,以此纪念 与二叉搜索树的区别 AVL树在二叉搜索树的基础上增加了新的限制:需要时刻保证每个树中每个结点的左右子树高度之差的绝对值不超过1 因此,当向树中插入新结点后,即可降低树的高度&…...

出口贸易媒体发稿推广6个技巧提升品牌知名度-华媒舍
1. 出口贸易媒体介绍 出口贸易媒体是指专注于报道国际贸易、跨境业务和进出口市场的媒体平台。这些媒体对于企业发展来说至关重要,可以帮助品牌扩大影响力、提升知名度,促进商业合作。下面介绍6个出口贸易媒体发稿推广技巧,帮助企业更好地利…...

学习笔记:CANOE模拟LIN主节点和实际从节点进行通信测试
先写点感想,在LIN开发阶段,我一般用图莫斯USB工具来进行模拟主机节点发送数据。后来公司买了CANOE工具就边学习边搭建了LIN的测试工程,网上的资料真的很少,主要是靠自己一点点摸索前进,总算入门。几个月后的今天&#…...

模型可解释性
模型可解释性 前言导读Background1、为什么需要可解释性?2、诞生背景3、研究现状4、常见的模型可解释性方法4.1 基于模型自身的可解释性1)Explanation Generation2)Prototype Network 4.2 基于结果的可解释性 5、应用前景6、面临挑战 前言导读…...

Django初窥门径-自定义用户模型
前言 自定义用户模型在Django应用中是一个重要的话题,它涉及到如何根据您的项目需求以及特定的用户身份验证和授权需求来调整用户模型。在以下前言中,我将讲述为什么自定义用户模型是如此重要以及其潜在的优势: 随着Web应用的不断发展&…...

微信小程序文件上传wx.uploadFile
网页版查看了一下负载要求是这样 wx.uploadFile({url: ${wx.getStorageSync(apiUrl)}//sysFileInfo/upload?token${wx.getStorageSync(token)}, // 仅为示例,非真实的接口地址filePath: files[0].url,name: file,formData: {secretFlag: Y },success: (res) > {…...

支持内录系统声音的Mac录屏软件Omi Recorder
Screen Recorder by Omi是一款功能强大的屏幕录制应用程序。它可用于在Windows和Mac计算机上捕获屏幕,以便进行演示、教程、游戏录制、视频编辑等各种用途。 以下是该应用程序的一些主要特点: 支持高清录制:Omi Screen Recorder可以以高达6…...

一、Hadoop初始化配置(final+ubuntu保姆级教程)
1、配置虚拟机 三台虚拟机,分别为node1、node2、node3,内存分别为4G、2G、2G,现存最好为(>40G),如下: 2、修改主机名 分别打开三台虚拟机,root用户输入一下命令: no…...
Linux常用的包管理工具
Linux系统中有两个常用的包管理工具,分别是yum和apt。 1. yum命令 yum是Red Hat公司开发的一种包管理器,主要用于安装、更新、卸载和管理RPM包。它是基于RPM包管理系统的,可以自动解决软件包依赖关系问题。 常用yum命令: - 安…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...

dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...

Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...

C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...

Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...