目录
1. BeanShell Sampler
1.1 BeanShell Timer:BeanShell定时器
1.2 BeanShell PreProcessor:BeanShell前置处理器
1.3 BeanShell Sampler:BeanShell取样器
2. Debug Sampler:调试取样器
3. FTP 请求:FTP取样器
4. Java 请求:Java取样器
4.1 自带的两个Java请求类
4.2 实例:模仿JavaTest和SleepTest,扩展Java请求元件
5. JDBC 请求:JDBC取样器
5.1 JDBC 连接池设置
5.2 添加 JDBC Request
6. JUnit Request
6.1 JUnit 简介
6.2 JUnit 参数
6.3 JMeter JUnit Request
7. SOAP/XML-RPC Request
7.1 WebServices目前主流的实现方式有三种
7.2 SOAP/XML-RPC Request
1. BeanShell Sampler
1.1 BeanShell Timer:BeanShell定时器
选项的含义,具体参考下方图片中的备注。
其中,Script脚本区域:可以在该区域写BeanShell脚本,在脚本中可以调用JMeter的运行属性。
(1)log:直接可以调用log类来写日志。比如log.error()。
(2)ctx:可以通过获取JmeterContent实例来获取运行时信息(线程数,线程状态等),比如ctx.getThreadNum()。
(3)vars:能够访问变量获取对应的值,也可以设置变量。比如vars.put("name", "Sheryl"), vars.get("name")。
(4)props:可以直接访问JMeter的属性,也可以设置属性值。JMeter的属性在jmeter.properties中。比如: props.put("log_level.jmeter","ERROR"), props.get("log_level.jmeter")。即 在运行过程中,我们可以用BeanShell来修改JMeter属性。
(5)prev:可以访问前面Sampler的结果。BeanShell支持调用Java方法的脚本语言。
BeanShell脚本语言语法: http://www.beanshell.org/
小结:
我们可以运用BeanShell来访问及设置属性,访问及设置变量,记录日志。
在定时器,前置处理器,后置处理器,Sampler,断言,监听器中,都可以用到BeanShell。
在JMeter中只要涉及到BeanShell的,脚本编写方式都一样,访问的资源也都一样。
JmeterContent(ctx)类的常用方法如下:
1.2 BeanShell PreProcessor:BeanShell前置处理器
1.3 BeanShell Sampler:BeanShell取样器
(1)BeanShell Sampler跟BeanShell定时器,BeanShell前置处理器等有共性。脚本一样,仅配置项有变化。
(2)BeanShell Sampler作为Sampler, 即用来模拟向被测系统发起请求,JMeter会记录取样结果(TPS,响应时间等性能指标)。
(3)BeanShell支持Java对象的调用,可直接通过BeanShell来调用Java程序(类似接口测试)。
(4)实例:BeanShell调用Java接口的例子
步骤:
1)编写Java程序
2)将Java程序打成jar包(参考:在IDEA中如何将Java程序打包成jar包)
3)把jar包加入JMeter脚本的类路径
4)在BeanShell取样器中编写BeanShell脚本
package com.seling.test;
public interface BeanUtil {
public String getUserName();
public String getAddress();
public int mul(int i);
}
package com.seling.test;
public class BeanShellEg implements BeanUtil{
private String userName;
private String address;
public BeanShellEg(String name){
this.userName = name;
}
public BeanShellEg(String name, String address){
this.userName = name;
this.address = address;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public int mul(int i) {
return i*i;
}
}
package com.seling.test;
public class BeanShellTest {
public static void main(String[] args) {
BeanShellEg bs = new BeanShellEg("Sheryl", "China");
System.out.println(bs.getUserName() + " is in " + bs.getAddress());
}
}
(5)如何将被引用的类加入到类加载路径
问题: 如果不加载被引用的类,则BeanShell找不到相应的类,运行报错。
解决办法有两个:
1)在测试计划中导入被引用的程序的jar包形式。
2)将引用包和依赖包放到JMeter默认的包加载路径:%JMETER_HOME%\lib。
引用包:是BeanShell程序调用的Java类所在的包。比如BeanShellTest1211.jar
依赖包:如果引用包中的类又依赖于其他包中的类,这个包就是引用包的依赖包,也需要发布到类加载路径。
即:直接引用或间接引用的包都需要发布到类加载路径。建议用该方法。
(6)BeanShell支持访问哪些属性和变量
上文BeanShell Timer能访问的属性和变量,BeanShell Sampler也匹配这些功能。
此外,作为Sampler, 它还多出4个项目:
1)SampleResult:可以访问Sampler对应的结果对象,即能够查询与编辑其中的属性。
2)ResponseCode:可以引用此属性自行设置Samler的返回码,一般http请求成功设置为200。
3)ResponseMessage:可以引用此属性自行设置响应消息内容,默认为OK。
4)IsSuccess:可以引用它来决定Sampler产生的事务是否成功。
2. Debug Sampler:调试取样器
Debug Sampler和察看结果树结合使用,可以满足下方的需求:
(1)参数化的变量取值是否正确
(2)正则表达式提取的值是否正确
(3)JMeter属性
(4)调试时服务器返回些什么内容
3. FTP 请求:FTP取样器
(1)FTP(文件传输协议)用于Internet上文件的双向传输。
作为一个应用程序,不同的操作系统也有不同的实现,为了保证可以跨平台,FTP程序都要遵循相同的协议,FTP有上传和下载两种功能。
(2)JMeter提供对FTP上传和下载的测试支持。FTP请求和FTP请求默认值设置基本一样,只是多了用户名和密码。
(3)页面属性如下图中的备注。实例演示:
4. Java 请求:Java取样器
4.1 自带的两个Java请求类
JMeter的Java取样器上自带两个Java请求类:JavaTest, SleepTest。
通常这两个类对我们测试没有实际作用,但可以模仿它们来扩展Java请求元件,用来做接口测试。
4.2 实例:模仿JavaTest和SleepTest,扩展Java请求元件
思路分析
(1)JavaTest类继承了AbstractJavaSamplerClient类,所以我们编写的类也要继承该类。
此时,需要实现类里的runTest()方法,在这个方法中,可以放入我们需要测试的接口。
(2)只有继承AbstractJavaSamplerClient类,在Java Sampler请求中才可以看到我们模仿的Java请求。
(3)执行过程中,可以将部分工作提取出来,放在setupTest(),tearDownTest()方法中。需要参数化的,可以暴露出参数表供用户进行参数化,这部分内容放在getDefaultParameters方法中。
示例工程:
(1)编写代码:
package com.seling.test;
public interface BeanUtil {
public String getUserName();
public String getAddress();
public int mul(int i);
}
package com.seling.test;
public class BeanShellEg implements BeanUtil{
private String userName;
private String address;
public BeanShellEg(String name){
this.userName = name;
}
public BeanShellEg(String name, String address){
this.userName = name;
this.address = address;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public int mul(int i) {
return i*i;
}
}
package com.seling.test;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;
import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
import org.apache.jmeter.samplers.SampleResult;
import java.io.Serializable;
public class BeanUtilTest extends AbstractJavaSamplerClient implements Serializable {
private static final long serialVersionUID = 5002930172848461734L;
private static final Log log = LogFactory.getLog(BeanUtilTest.class);
private BeanUtil bu;
//Java Sampler界面中展示用来指导用户输入变量
public Arguments getDefaultParameters(){
Arguments args = new Arguments();
args.addArgument("i", "i.value");
return args;
}
//执行runTest方法之前会调用此方法
public void setupTest(JavaSamplerContext context){
bu = new BeanShellEg("Lili", "Germany");
}
//此方法中调用需要测试的接口
//@param context JavaSampler 上下文
//@return SamplerResult 返回对象用来记录取样器结果
@Override
public SampleResult runTest(JavaSamplerContext context) {
//获取用户输入的变量值
int i = Integer.valueOf(context.getParameter("i"));
//实例化SamplerResult, 用来记录运行结果
SampleResult sr = new SampleResult();
//定义事务的开始
sr.sampleStart();
int mul = bu.mul(i);
//设置事务结束
sr.sampleEnd();
//设置事务成功
sr.setSuccessful(true);
//设置Java Sampler标题
sr.setSampleLabel("mul");
//设置响应成功
sr.setResponseCodeOK();
//设置响应内容
sr.setResponseData("mul result: " + String.valueOf(mul));
return sr;
}
//执行runTest方法后会调用此方法
public void tearDownTest(JavaSamplerContext context){
}
}
(2)打包我们编写的BeanUtilTest类。
打包好BeanUtilTest后,放到%JMETER_HOME%\lib\ext目录下。如果程序依赖于另一个BeanShell.jar包,则BeanShell.jar包需要放入%JMETER_HOME%\lib目录。
注意:
这两个目录不同。
BeanUtilTest.jar是JMeter启动时会加载到Java Sampler元件中的,属于扩展包,需要放在%JMETER_HOME%\lib\ext目录下。
而BeanShell.jar是被依赖的包,放在%JMETER_HOME%\lib目录下(也可以在测试计划中加入)。
(3)重启JMeter, 此时在Java请求元件页面的类名称下拉表中,就能看到扩展的BeanUtilTest类。
(4)调试脚本,增加断言元件等等。
遇到的问题:
在实际操作时,在IDEA中编写了上述三个类,然后打包成jar包。这三个类没有main方法,貌似是因为这个原因,导致打包过程出了问题,虽然可以打包成一个jar包,也放到了 %JMETER_HOME%\lib\ext目录下了,但是此时想要启动JMeter,报错,启动失败。当在项目的out目录下删除了这个jar包后,JMeter才能启动成功。
具体原因还未知,可能是我对过程中某个内容的理解还不到位,进而导致错误,后续会再排查,然后重新操作一遍。到时再更新。
5. JDBC 请求:JDBC取样器
当需要对数据库进行测试,比如想测试一个SQL性能如何,测试一个存储过程性能如何。
JMeter提供了程序,帮我们建立了连接池,连接池的配置由我们自行配置,然后又提供程序来执行我们的SQL语句,提供参数化的功能。
局限:一个JDBC request只能执行一条语句。
5.1 JDBC 连接池设置
补充知识点:
(1)数据库事务的ACID和隔离级别
1)数据库事务的性质:ACID
A 原子性:atomicity,事务是数据库的逻辑公祖哦单位,对于其数据修改,要么全部执行,要么全部不执行。
C 一致性:consistency,事务在完成时,必须是所有的数据都保持一致状态。在相关数据库中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。
I 隔离性:isolation,一个事务的执行不能被其他事务所影响。
D 持久性:duration,一个事物一旦提交,事务的操作边永久性的保存在数据库中。即使此时再执行回滚操作也不能撤销所做的更改。
2)锁机制,用来隔离事务。几种隔离级别:
TRANSACTION_NONE:不支持事务,=0
TRANSACTION_READ_UNCOMMITTED:允许脏读,不可重复读和幻读,=1
TRANSACTION_READ_COMMITED:禁止脏读,但允许不可重复读和幻读,=2
TRANSACTION_REPEATABLE_READ:禁止脏读和不可重复读,允许幻读,=4
TRANSACTION_SERIALIZABLE:禁止脏读,不可重复读和幻读,=8
default:JMeter加上去的,其实是TRACNSACTION_READ_COMMITED。
3)3种读现象
脏读:一个事务读取了另一个事务未提交的数据
不可重复读:一个事务再次读取之前的数据时,这个数据已经被另外一个事务修改
幻读:一个事务重新执行一个查询,返回的记录包含了其他事务提交的新纪录
(2)JDBC连接字符是固定的,不同的数据,这个链接字符有差别,常见的连接字符如下:
1)MySQL
Driver="com.mysql.jdbc.Driver";
URL="jdbc:mysql://localhost:{端口}/{数据库名}";
2)Oracle
Driver="oracle.jdbc.driver.OracleDriver";
URL="jdbc:oracle:thin:@localhost:{端口}:{SID}";
3)Microsoft SQL Server
Driver="com.microsoft.sqlserver.jdbc.SQLServerDriver";
URL="jdbc:microsofr:sqlserver://localhost::{端口}: DatabaseName={数据库名}";
4)Sysbase
Driver="com.sybase.jdbc.SybDriver";
URL="jdbc:Sysbase://localhost:{端口}/{数据库名}";
5)PostgreSQL
Driver="org.postgresql.Driver";
URL="jdbc:postgresql://localhost/db_name";
6)DB2
Driver="com.ibm.db2.jdbc.app.DB2.Driver";//装有DB2客户端
Driver="com.ibm.db2.jdbc.net.DB2.Driver"; //未装DB2客户端
URL="jdbc:db2://localhost:{端口}/{数据库名}";
7)JDBC-ODBC
Driver="sun.jdbc.odbc.JdbcOdbcDriver";
URL="jdbc:odbc:{数据源名}";
注意:
需要把用到的驱动包放到%JMETER_HOME%\lib目录下。比如用MySQL的话,需要把MySQL JDBC驱动包 mysql-connector-java-5.0.7-bin.jar放到目录%JMETER_HOME%\lib下。
附:C3p0连接池配置官网地址如下,用于C3p0连接池的配置调优。
c3p0-v0.9.5.5 - JDBC3 Connection and Statement Pooling - Documentation (mchange.com)
5.2 添加 JDBC Request
(1)Query Type说明:
Select Statement:在需要执行查询语句的时候用到
Update Statement:执行更新操作的时候用到,包括插入和修改
Callable Statement:读音JDBC规范中的CallableStatement对象,为所有的DBMS提供了一种以标准形式调用存储过程的方法。即可以调用存储过程,可以入参,有占位符。
Prepared Select Statement:预编译查询语句。在Oracle中为了减少护具库在SQL上的硬编译资源消耗,提倡大家用绑定变量,这样相同的SQL只会被编译一次。
Perpared Update Statement:这个只是把上面的Select换成update,意义一样。
Commit:当前连接状态中的内容提交
Rollback:当前连接状态中的内容回滚
AutoCommite(false) :指明不需要自动提交
(2)JDBC Request的实例演示
(稍后补)
6. JUnit Request
经常用JUnit来完成单元测试。JMeter提供了对JUit程序的支持。重点在JUnit4。
6.1 JUnit 简介
JUnit是一个单元测试框架。多数Java集成开发环境都已经集成了JUnit作为单元测试工具。
JUnit能够测试程序,可以利用它作为性能测试脚本进行性能测试。
常见注解:
@Before
@After
@BeforeClass
@AfterClass
@Test(timeout=xxx)
@Test(expected=Exception.class)
@Ignore
示例:略
注意:
使用Junit时,需要加上hamcrest-core-XX.jar包。建议组合:hamc-core-1.3.jar和junit-4.11.jar
6.2 JUnit 参数
测试是可能会需要用多组参数来测试程序是否正确,这就需要JUnit能够支持参数化功能。
示例稍后补。
说明:
(1)在JUnit测试类中定义了一个静态的方法initData(),来组装参数值,返回Collection对象。
(2)定义了两个成员变量name和address,然后用构造方法来对这两个成员变量赋值。
(3)在执行时即可正常读取到参数。
使用到的注解:
(1)@RunWith:指定用RunWith运行器,JUnit有多个运行期,RunWith支持读取参数,表名此测试类哟读取参数。
(2)@Parameters:定义此方法进行参数组装,注意此方法是Static的,并且返回的是集合,可以用来循环遍历。而且这个集合至少要是一个二维数组。如果只需要一个参数,则不给数组的第二个维度赋值即可。
6.3 JMeter JUnit Request
开始JMeter JUnit Request的开发:
(1)编写JUnit程序,将其打包成jar包,放到%JMETER_HOME%\lib\junit目录下。
(2)启动JMeter,添加JUnit Request, 选择Search for JUnit4 annotations
(3)运行,观察结果(察看结果树,控制台)
(具体演示,稍后补)
7. SOAP/XML-RPC Request
7.1 WebServices目前主流的实现方式有三种
(1)REST
(2)SOAP
(3)XML-RPC