性能测试工具 Jmeter 做 Http 接口测试 :编写自定义函数

news2024/12/30 4:13:29

目录

一、 前言

二、 编写自定义函数的步骤

1. 新建一个工程,导入 jmeter jar 包。

2. 新建 package:stressTest.functions

3. 新建一个类继承 AbstractFunction,重写以下方法:

4. 打包

5. 将打出来的 jar 包拷贝至 jmeter 的目录:

6. 运行

7. 测试


一、 前言

在JMeter中进行HTTP接口测试时,编写自定义函数可以帮助我们更灵活地处理测试数据和参数化请求。自定义函数可以根据特定的需求生成动态的测试数据,从而增加测试的覆盖范围和准确性。

比如最近一个项目,在发送 http 请求的时候,客户端需要发 Token,它是根据给项目分配的 ID 和 Key 值以及系统当前时间生成的,服务端会验证该 Token 的有效性。

开发自定义函数,网上一般有两种做法:

  • 修改 jmeter 源码,增加一个函数,重新导出 jmeter 的 jar 包,放入 jmeter 的 lib 目录。
  • 新建一个项目,导入 jmeter 原生 jar 包,继承虚基类,编写新函数,打包,放入 jmeter 的 lib 目录。

第一种方法既复杂,又不易于维护管理,我个人喜欢用第二种方法。

第二种方法的大坑就是 package 命名有特殊的要求:package 路径中必须包含 functions 一级。

二、 编写自定义函数的步骤

1. 新建一个工程,导入 jmeter jar 包。

我用 maven 管理项目,因此只需要在 pom 文件中加入以下引用。

<dependency>
     <groupId>org.apache.jmeter</groupId>
     <artifactId>ApacheJMeter_java</artifactId>
     <version>3.0</version>
 </dependency>
 <dependency>
     <groupId>org.apache.jmeter</groupId>
     <artifactId>ApacheJMeter_core</artifactId>
     <version>3.0</version>
 </dependency>
2. 新建 package:stressTest.functions

注意:路径中必须包含 functions,否则 jmeter 无法识别。JMeter 设计让一些核心的类(非 UI 相关的,比如 ApacheJMeter_core 等)可以在非 UI 的方式下运行的时候能被加载进来,这些类会被优先加载。加载这些类的时候是通过命名规则来实现的。所有实现 function 的类必需包含".functions."。
当然也可以通过更改 jmeter.properties 中的配置来实现改变命名规则,如下所示。但是一般来说不推荐更改此项配置。

classfinder.functions.contain=.functions.
3. 新建一个类继承 AbstractFunction,重写以下方法:
  • execute
  • setParameters
  • getReferenceKey
  • getArgumentDesc

这四个方法介绍如下:

public String execute(SampleResult previousResult, Sampler currentSampler) throws InvalidVariableException

JMeter 会将上次运行的 SampleResult 和当前的 Sampler 作为参数传入到该方法里,返回值就是在运行该 function 后得到的值,以 String 类型返回。该方法如果操作了非线程安全的对象(比如文件),则需要将对该方法进行线程同步保护。

public void setParameters(Collection<CompoundVariable> parameters) throws InvalidVariableException;

这个方法在用于传递用户在执行过程当中传入的实际参数值。该方法在 function 没有参数情况下也会被调用。一般该方法传入的参数会被保存在类内全局变量里,并被后面调用的 execute 方法中使用到。

public String getReferenceKey();

这个就是 function 的名字。JMeter 的命名规则是在方法名前面加入双下划线"__"。比如"__GetEven",function 的名字跟实现该类的类名应该一致,而且该名字应该以 static final 的方式在实现类中定义好,避免在运行的时候更改它。

public List<String> getArgumentDesc();

最后在你的实现类中还需要提供一个方法来告诉 JMeter 关于你实现的 function 的描述。

我自己编写的 GetToken 类如下:

package stressTest.functions;

import org.apache.jmeter.engine.util.CompoundVariable;
import org.apache.jmeter.functions.AbstractFunction;
import org.apache.jmeter.functions.InvalidVariableException;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.samplers.Sampler;
import org.apache.jmeter.util.JMeterUtils;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.util.encoders.Hex;

import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

/**
 * Created by pengshenshen on 2018/3/12.
 */
public class GetToken extends AbstractFunction {

    private static final List<String> desc = new LinkedList<String>();
    private static final String KEY = "__getToken";
    private CompoundVariable[] values;

    // Number of parameters expected - used to reject invalid calls
    private static final int MIN_PARAMETER_COUNT = 2;
    private static final int MAX_PARAMETER_COUNT = 3;

    static {
        desc.add(JMeterUtils.getResString("appId"));
        desc.add(JMeterUtils.getResString("apiKey"));
    }

    @Override
    public String execute(SampleResult sampleResult, Sampler sampler) throws InvalidVariableException {
        String appId = values[0].execute();
        String apiKey = values[1].execute();
        long currentTimeMillis = System.currentTimeMillis();
        // 5 minutes
        currentTimeMillis = currentTimeMillis - (currentTimeMillis % (1000 * 60 * 5));
        byte[] data = (appId + apiKey + currentTimeMillis).getBytes();
        MD5Digest md5 = new MD5Digest();
        md5.update(data, 0, data.length);
        byte[] digest = new byte[md5.getDigestSize()];
        md5.doFinal(digest, 0);
        return Hex.toHexString(digest);
    }

    @Override
    public void setParameters(Collection<CompoundVariable> parameters) throws InvalidVariableException {
        checkParameterCount(parameters, MIN_PARAMETER_COUNT, MAX_PARAMETER_COUNT);
        values = parameters.toArray(new CompoundVariable[parameters.size()]);
    }

    @Override
    public String getReferenceKey() {
        return KEY;
    }

    @Override
    public List<String> getArgumentDesc() {
        return desc;
    }
}

4. 打包

我用 maven-assembly-plugin 打包。方法如下:
首先在 pom 文件中引入插件:

<plugin>
<artifactId>maven-assembly-plugin</artifactId><configuration>
    <descriptorRefs>
        <descriptorRef>jar-with-dependencies</descriptorRef>
    </descriptorRefs>
</configuration>
</plugin>

然后执行打包命令:mvn clean compile assembly:single

5. 将打出来的 jar 包拷贝至 jmeter 的目录:

将打出来的 jar 包拷贝至 jmeter 的目录:Jmerter_HOME\lib\ext

6. 运行

Jmerter_HOME\bin\jmeter.bat,在函数助手界面中可以找到我的函数:

7. 测试

随便做一个 post 请求,测试该方法是否有效

向百度发一个 post 请求,查看一下 body 里面传 getToken 函数的结果

如图:在查看结果树中看到:请求的 body 中已经带了 Token 值。

  作为一位过来人也是希望大家少走一些弯路

在这里我给大家分享一些自动化测试前进之路的必须品,希望能对你带来帮助。

(WEB自动化测试、app自动化测试、接口自动化测试、持续集成、自动化测试开发、大厂面试真题、简历模板等等)

相信能使你更好的进步!

点击下方小卡片

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/747917.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

学习记录——BiSeNetV1、BiSeNetV2、BiSeNetV3、PIDNet、CMNeXt

BiSeNetV1 BiSeNetV1为了在不影响速度的情况下&#xff0c;同时收集到空间信息和语义信息&#xff0c;设计了两条路&#xff1a; Spatial Path: 用了三层stride为 2 的卷积&#xff0c;卷积BNRELU模块。最后提取了相当于原图像 1/8 的输出特征图。由于它利用了较大尺度的特征图…

怎样把手机录音转换成文字免费?分享3个免费方法给给大家!

将手机录音转换为文字可以提高工作和学习效率&#xff0c;但很多人不知道如何实现。在本文中&#xff0c;我将分享三个免费的方法来帮助您将手机录音转换为文字&#xff0c;分别是使用记灵在线工具&#xff08;网页&#xff09;、微信和剪映。无论您是需要转录会议记录、课堂笔…

界面控件DevExtreme UI组件——增强的API功能

虽然DevExtreme刚刚发布了v23.1&#xff0c;但今天我们仍然要继续总结一下之前的主要更新&#xff08;v22.2&#xff09;中发布的一些与DevExtreme API相关的重要特性。 DevExtreme拥有高性能的HTML5 / JavaScript小部件集合&#xff0c;使您可以利用现代Web开发堆栈&#xff…

C语言 — 指针进阶篇(上)

前言 指针基础篇回顾可以详见&#xff1a; 指针基础篇&#xff08;1&#xff09;指针基础篇&#xff08;2&#xff09; 指针进阶篇分为上下两篇,上篇介绍1 — 4&#xff0c;下篇介绍5 — 6 字符指针数组指针指针数组数组传参和指针传参函数指针函数指针数组指向函数指针数组的…

Leetcode-每日一题【147.对链表进行插入排序】

题目 给定单个链表的头 head &#xff0c;使用 插入排序 对链表进行排序&#xff0c;并返回 排序后链表的头 。 插入排序 算法的步骤: 插入排序是迭代的&#xff0c;每次只移动一个元素&#xff0c;直到所有元素可以形成一个有序的输出列表。 每次迭代中&#xff0c;插入排序…

MySQL分区表详解

目录 分区表介绍 分区适用场景 分区方式 分区策略 常见分区命令 1. 分区表介绍 MySQL 数据库中的数据是以文件的形势存在磁盘上的&#xff0c;默认放在 /var/lib/mysql/ 目录下面&#xff0c;我们可以通过 show variables like %datadir%; 命令来查看&#xff1a; 我们进入…

a标签form表单,转发,重定向

a标签需要写项目名,form表单需要写项目名,转发写请求路径,重定向需要写项目名 // window.location.href"请求路径" 需要写项目名 // window.location"请求路径" 需要写项目名 // document.location.href"请求路径" 需要写项目名 …

业务流程图怎么画?这几种绘制方法看一看

业务流程图怎么画&#xff1f;流程图提供了对业务流程的清晰概述&#xff0c;帮助人们理解工作流程中涉及的活动、决策和步骤。它定义了任务的顺序和依赖关系&#xff0c;使人们能够更好地了解整个流程。通过绘制流程图&#xff0c;可以更容易地识别出潜在的问题、瓶颈和延迟。…

SOPC之NiosⅡ系统(一)

1. 基础概念 1.1 CPU软核与硬核 简单来说 CPU硬核就是在FPGA上的一颗硬件结构固定并且用户不能对其结构进行任何更改、只能进行编程控制的芯片。 CPU软核则是FPGA上本来不存在这样的硬件结构&#xff0c;用户可根据硬件描述语言利用NIOS Ⅱ软核搭建出一个CPU。 1.2 SOC和S…

面试题大杂烩-记不住

1、分库分表图啥 分库是为了解决单库io连接数的瓶颈 分表是为了解决单表效率瓶颈 2、分表后如何limit分页 如果是根据xxx字段进行分表的话 那么shardingjdbc会根据字段进行笛卡尔积计算 去对应表里面执行sql到内存中计算&#xff0c;比如根据用户id进行hash算法进行查表&…

如何选择软文发布平台?软文发布平台的分类、特点及推广策略

在现今的市场竞争中&#xff0c;软文作为一种重要的推广方式&#xff0c;受到了越来越多企业的关注和运用。而软文发布平台&#xff0c;则是软文营销过程中不可或缺的一个环节&#xff0c;不同的软文发布平台会对软文的传播效果产生重要影响。本文将从软文发布平台的分类、特点…

淘宝APP商品详情源数据接口代码分享(API接口系列可高并发)

电商平台APP商品详情源数据接口代码分享如下&#xff1a; 商品数据&#xff1a;淘宝提供了商品的基本信息&#xff0c;包括商品名称、描述、规格、价格、销量、库存等信息。此外&#xff0c;也可以通过淘宝提供的API接口来获取商品的图片、评价、物流信息等详细数据。 公共参数…

深入理解DRF中的Mixin类

DRF官网地址&#xff1a; Home - Django REST framework Generic views - Django REST framework 一、Mixin类介绍 1.1 Mixin类介绍 Mixin类是一种常见的设计模式&#xff0c;在多个类之间共享功能或行为时非常有用。 一个Mixin类通常包含一组方法或属性&#xff0c;可以被…

unity 使用vrtk4的插件 打包htv vive VR客户端包,手柄不生效

背景&#xff1a; 目的&#xff1a;u3d使用vrtk开发pico应用(vrtk是为了到时候无缝衔接后续要买的htc vive pro 2) 先导入了tilia importer&#xff08;也就是vrtk4.0&#xff0c;根据教程模块化使用功能&#xff09;和pico官网下的“PICO Unity IntegrationSDK-214-20230302…

Leetcode-每日一题【138.复制带随机指针的链表】

题目 给你一个长度为 n 的链表&#xff0c;每个节点包含一个额外增加的随机指针 random &#xff0c;该指针可以指向链表中的任何节点或空节点。 构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成&#xff0c;其中每个新节点的值都设为其对应的原节点的值。新节…

手捏Java知识点

今天开始面向对象了 面向对象基础 类&#xff1a;由属性和行为组成属性&#xff1a;在类中通过成员变量来体现行为&#xff1a;在类中通过成员方法来体现public class 类名{//成员变量变量1的数据类型 变量1;变量2的数据类型 变量2;...//成员方法方法1;方法2;...}有几个重要的概…

百度iOS端长连接组件建设及应用实践

作者 | 百度消息中台团队 导读 在过去的十年里&#xff0c;移动端技术飞速发展&#xff0c;移动应用逐渐成为主要的便捷访问和使用互联网的方式&#xff0c;承接了越来越多的业务和功能&#xff0c;这也意味着对移动端和服务器之间的通信效率和稳定性提出了更高的要求。为了实现…

ellisys 过滤设备

1、通过关键字过滤 输入蓝牙名称关键字&#xff0c;比如下面输入的是BNCM Transmitter "*BNCM*" || Receiver "*BNCM*" 之后&#xff0c;所有与这个设备相关的信号都会抓取过滤出来 2、通过地址过滤 之后&#xff0c;所有与这个设备相关的信号都会抓取过…

港联证券-深夜,大利好!人民币暴拉超500点,全球股市大反攻

全球商场一夜狂欢。 美国通胀大降温&#xff0c;全球危险资产全线大涨。北京时间7月12日晚间&#xff0c;美国劳工统计局发布数据&#xff0c;美国6月CPI同比涨幅回落至3%&#xff0c;低于预期3.1%&#xff0c;接连第12个月下降&#xff0c;且为2021年3月以来最低。数据发布后&…

02 |「Android Studio 新建项目」

前言 新手入门安卓开发 文章目录 前言一、步骤一、步骤 New Project选择 Empty Activity1)Name:项目的名字; 2)Package name:项目的包名(项目的唯一标识); 3)Save location:项目的保存路径; 4)Language: