京东质量社区 Jmeter Sampler (取样器插件开发) 制定自己的 Sampler

taki for 京东 · March 29, 2016 · Last by cc replied at March 04, 2018 · 3589 hits
本帖已被设为精华帖!

Jmeter可以帮助我们做性能测试、接口测试,然而Jmeter支持常用的HTTP等协议,如果某个公司采用自由协议那么Jmeter要采用实现【JavaSamplerClient】接口,这种方式当然是比较好的,但是有些东西和Jmeter自身的参数化等等功能,不太好结合,有的还有BUG,当然这个最灵活的,当然也可以采取做一个协议插件,嵌入到Jmeter中,那么怎么做呢?

1. 首先第一个做一个测试的GUI,要实现AbstractSamplerGui 类做才能被Jmeter加载


public class DemoSampleGui extends AbstractSamplerGui implements ItemListener {
private DemoParamConfigGui demoParamConfigGui;

public DemoSampleGui() { //构造方法初始化
init();
}
/**
* @Descrition初始化
* */

private void init() {
setLayout(new BorderLayout(0, 5));
setBorder(makeBorder());
add(makeTitlePanel(), BorderLayout.NORTH); //设置布局

demoParamConfigGui = new DemoParamConfigGui(); //这里是另外一个面板类,抽出去了,一会单独说
add(demoParamConfigGui, BorderLayout.CENTER);
}
/**
* @Descrition清除页面数据信息
* */

@Override
public void clearGui() {
super.clearGui();
demoParamConfigGui.clear();
}
/**
* @Descrition:配置组装元素信息
* */

@Override
public void configure(TestElement element) {
super.configure(element);
final MySamplerSamplerBase samplerBase = (MySamplerSamplerBase) element;
safParamConfigGui.configure(element);
}

/**
* @Descrition:创建新的元素
* */

@Override
public TestElement createTestElement() {
MySamplerSamplerBase sampler = new MySamplerSamplerBase();
modifyTestElement(sampler);
return sampler;
}
/**
* @Descrition:清除旧的组件,从新创建
* */

@Override
public void modifyTestElement(TestElement sampler) {
sampler.clear();
safParamConfigGui.modifyTestElement(sampler);
this.configureTestElement(sampler);
}
/**
* @Descrition:label信息,也就是创建HTTP请求、JAVA请求
* */

@Override
public String getLabelResource() {
return "mySampler_title";
}
}

Label那个由于Jmeter实现国际化,所以在配置文件里,通过mySampler_title去资源文件里面找的,如果我们想添加自己的需要修改CORE里面的配置文件,增加自己对应的UICODE编码


2.DemoParamConfigGui 类,这个类主要是初始化面板信息,和修改信息用的,我简单列几行代码,下面给最终的截图,这里可以根据自己的要求更改

public class MySamplerParamConfigGui extends JPanel{
public JTextField interfaceName;
public JTextField interfaceAddress;
public JTextField interfaceGroup;
public JTextField interfaceVersion;
public JTextField interfaceMethod; //定义几个页面输入框,这个根据自身需要开发哈,我这个是简单的例子
/**
* @Descrition:初始化面板
* */

private void init() {
setLayout(new BorderLayout(0, 5));
if (displayName) {
setBorder(makeBorder());
add(makeTitlePanel(), BorderLayout.NORTH);
}
// MAIN PANEL
VerticalPanel mainPanel = new VerticalPanel();
JPanel serverPanel = new HorizontalPanel();
serverPanel.add(createInterfaceAddressPanel(), BorderLayout.CENTER);
mainPanel.add(serverPanel);
mainPanel.add(createInterfaceNamePanel());
mainPanel.add(getInterfaceGroupPanel());
mainPanel.add(createInterfaceVersionPanel());
mainPanel.add(createInterfaceMethodPanel());
mainPanel.add(createJarFilePathPanel());
add(mainPanel, BorderLayout.CENTER);
}

/**
* @Descrition:创建文本框信息
* */

private JPanel createInterfaceMethodPanel() { //初始化上面文本对象,这里我列举一个例子,剩下都一下就是信息和布局的区别
interfaceMethod = new JTextField(15);
JLabel label = new JLabel("调用方法:"); // $NON-NLS-1$
label.setLabelFor(interfaceMethod);
JPanel panel = new JPanel(new BorderLayout(5, 0));
panel.add(label, BorderLayout.WEST);
panel.add(interfaceMethod, BorderLayout.CENTER);
return panel;
}


3.Sampler相关的类


public class MySamplerSamplerBase extends AbstractSampler
implements TestStateListener, TestIterationListener, ThreadListener, Interruptible {
////////////////////// Code ///////////////////////////

public MySamplerSamplerBase() {
setArguments(new Arguments());
}
public void setInterfaceName(String newInterfaceName) {
this.setProperty(InterfaceName, newInterfaceName);
}
public String getInterfaceAddress() {
return getPropertyAsString(InterfaceAddress);
}
public String getInterfaceName() {
return getPropertyAsString(InterfaceName);
}
public void setInterfaceGroup(String newInterfaceGroup) {
this.setProperty(InterfaceGroup, newInterfaceGroup, "");
}
public String getInterfaceGroup() {
return getPropertyAsString(InterfaceGroup, "");
}
public String getInterfaceVersion() {
return getPropertyAsString(InterfaceVersion);
}
public String getInterfaceMethod() {
return getPropertyAsString(InterfaceMethod);
} //这些都是从界面获取数据

/**
* @Descrition:设置参数
* */

public void setArguments(Arguments value) { //设置和获取参数
setProperty(new TestElementProperty(ARGUMENTS, value));
}

/**
* @Descrition:获取参数
* */

public Arguments getArguments() {
return (Arguments) getProperty(ARGUMENTS).getObjectValue();
}

/**
* @Descrition:执行sampler这个非常重要了,是执行sampler的地方
* */

@Override
public SampleResult sample(Entry e) {
return sample();
}

private transient MySamplerAbstractImpl impl; //sampler执行类的抽象类,
/**
* @Descrition:执行sampler
* */

public SampleResult sample() {
SampleResult res = null;
try {
if (impl == null) { //这里面可以做工厂模式,处理不同的协议sampler
impl = new MySamplerTestSampler(this);
List argumentList=getArgumentList(); //获取参数数据,默认的HTTP请求就是在这里组装带参数的URL,传入不同的client的
res = impl.sample(argumentList);
res.setSampleLabel(getName());
}
return res;
} catch (Exception e) {
return errorResult(e, new SampleResult());
}
}
/**
* @Descrition: 这里面组装表格传过来的数据,传LIST过去 ,这里可以任意自己处理数据格式
* */

public List getArgumentList() {
List<MySamplerArgument> list = new ArrayList();
PropertyIterator iter = getArguments().iterator();
while (iter.hasNext()) {
MySamplerArgument item = null;
Object objectValue = iter.next().getObjectValue();
try {
item = (MySamplerArgument) objectValue;
list.add(item);
} catch (ClassCastException e) {
log.warn("Unexpected argument type: " + objectValue.getClass().getName());
item = new MySamplerArgument((Argument) objectValue);
}
}
return list;
}
}

*4.具体sampler执行类,具体的协议请求发起客户端要你自己定义了,集成到Jar包里就行,所有的类编写完成打JAR包扔到Jmeter/lib/ext下
*


public class MySamplerTestSampler extends MySamplerAbstractImpl {

@Override
protected SampleResult sample(List list) { //因为我定时的是list类型 所以这里面是list
SampleResult res = new SampleResult();
SampleResult res = new SampleResult();
System.out.println("list:"+list.toString());
try {
String interfaceAddress = getInterfaceAddress();
System.out.println("interfaceAddress:"+interfaceAddress);
String interfaceName = getInterfaceName();
res.setSamplerData("interfaceAddress:"+interfaceAddress+"interfaceName:"+interfaceName);
res.sampleStart();
res.setResponseData("list参数:"+list.toString(),"UTF-8");
} catch (RuntimeException e) {
res.setResponseCode("500");
res.setSuccessful(false);
res.setResponseMessage(e.toString());
e.printStackTrace();
return res;
} catch (Exception e) {
res.setResponseCode("500");
res.setSuccessful(false);
res.setResponseMessage(e.toString());
e.printStackTrace();
return res;
} finally {
res.sampleEnd();
}
return res;
}
}

5.演示




共收到 10 条回复 时间 点赞

过几天我自己实践下, 遇到不明白再来请教下.

正是我想要的,话说这些自定义插件开发在官网有示例不

taki #3 · March 30, 2016 作者

#2楼 @rennixing 官网好像是没有的,我不太确定

—— 来自TesterHome官方 安卓客户端

我想问下,多个接口有耦合关系的情况下,怎么弄?比如登陆成功后返回给token...然后把token传给其他接口等,类似的

taki #5 · April 05, 2016 作者

#4楼 @lose 和http 的一样

你好,请问那个键值对形式的输入参数界面,是用jmeter哪个方法实现的?或者能不能麻烦给一下configGUI类的代码? 多谢🙏

taki #7 · June 27, 2017 作者
小郑 回复

说实话我忘记了····

taki 回复

configGUI的代码还在吗?

注册中心要卸载xml中,把地址写在前台。直接传入到xml的zookeeper配置那里吗?

能加下您qq或微信吗,我有问题想问下?

需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up