谈到性能测试,部分公司连专门用于性能测试的环境都没有,更别提性能测试框架/平台了。下面,笔者就“基于Jmeter的性能测试框架搭建”这个话题,谈谈自己的一些想法。
为了简便测试人员操作,特开发此压测小工具,实现功能如下:
使用JGit访问Gitlab,dom4j处理xml文件。pom.xml配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.tool</groupId>
<artifactId>performanceTestTool</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>6</source>
<target>6</target>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>jgit-repository</id>
<url>https://repo.eclipse.org/content/groups/releases/</url>
</repository>
</repositories>
<!-- Core Library -->
<dependencies>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit</artifactId>
<version>4.11.0.201803080745-r</version>
</dependency>
<!-- Smart HTTP Servlet -->
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit.http.server</artifactId>
<version>4.11.0.201803080745-r</version>
</dependency>
<!-- AWT UI Helpers -->
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit.ui</artifactId>
<version>4.11.0.201803080745-r</version>
</dependency>
<!-- JUnit Test Support -->
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit.junit</artifactId>
<version>4.11.0.201803080745-r</version>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
</dependencies>
</project>
clone项目至本地仓库:
public static void cloneProject() throws Exception {
//每次clone前先初始化
Util.deletefile(localProject);
File file = new File(localProject);
try {
//克隆代码库命令
CloneCommand cloneCommand = Git.cloneRepository();
cloneCommand.setURI(remoteRepoURI) //设置远程URI
.setBranch("master") //设置clone下来的分支
.setDirectory(file) //设置下载存放路径
.setCredentialsProvider(usernamePasswordCredentialsProvider)
.call();
} catch (GitAPIException e) {
e.printStackTrace();
}
}
pull操作:
public static void pullFiles() throws IOException, GitAPIException {
//git仓库地址
Git git = new Git(new FileRepository(localProject+"/.git"));
git.pull().setRemoteBranchName("master").
setCredentialsProvider(usernamePasswordCredentialsProvider).call();
}
push操作:
public static void pushFiles(String filePath,String commitMess) throws IOException, GitAPIException {
File fileFrom = new File(filePath);
File fileTemp = new File(localProject);
File fileTo = new File(fileTemp.getAbsolutePath()+"/"+fileFrom.getName());
fileTo.createNewFile();
Util.copyFiles(fileFrom,fileTo); //拷贝脚本文件至git本地仓库
Repository rep = new FileRepository(localProject+"\\.git");
Git git1 = new Git(rep);
git1.add().addFilepattern(fileFrom.getName()).call(); //此处必须使用本地仓库中需推送的文件名
git1.add().addFilepattern("build.xml").call(); //push修改后的build文件
//提交
git1.commit().setMessage(commitMess).call();
git1.push().setCredentialsProvider(usernamePasswordCredentialsProvider).call();
}
build.xml文件配置:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project basedir="." default="run" name="Ant">
<tstamp>
<format pattern="yyyyMMddhhmm" property="time"/>
</tstamp>
<!-- jmeter路径-->
<property name="jmeter.home" value="D:\tools\PerformanceTesting\Jmeter_influxdb_grafana\apache-jmeter-3.1"/>
<!-- jmeter jtl测试报告生成路径-->
<property name="jmeter.result.jtl.dir" value="D:\tools\PerformanceTesting\Jmeter_influxdb_grafana\apache-jmeter-3.1\TestCase\report\jtl"/>
<!-- jmeter html测试报告生成路径-->
<property name="jmeter.result.html.dir" value="D:\tools\PerformanceTesting\Jmeter_influxdb_grafana\apache-jmeter-3.1\TestCase\report\html"/>
<!-- 参数化-->
<property name="ReportName" value="TestReport"/>
<property name="jmeter.result.jtlName" value="${jmeter.result.jtl.dir}/${ReportName}${time}.jtl"/>
<property name="jmeter.result.htmlName" value="${jmeter.result.html.dir}/${ReportName}${time}.html"/>
<target name="run">
<antcall target="test"/>
<!--性能脚本构建时,生成报告时间太长,注释掉 -->
<!-- antcall target="report"/ -->
</target>
<target name="test">
<taskdef classname="org.programmerplanet.ant.taskdefs.jmeter.JMeterTask" name="jmeter"/>
<jmeter jmeterhome="${jmeter.home}" resultlog="${jmeter.result.jtlName}">
<!-- 构建路径,与jenkins上工作空间配置保持一致 -->
<testplans dir="D:\tools\PerformanceTesting\Jmeter_influxdb_grafana\apache-jmeter-3.1\TestCase\jenkins_jobworkspace" includes="测试.jmx"/>
<property name="jmeter.save.saveservice.output_format" value="xml"/>
</jmeter>
</target>
<target name="report">
<xslt in="${jmeter.result.jtlName}" out="${jmeter.result.htmlName}" style="${jmeter.home}/extras/jmeter.results.shanhe.me.xsl"/>
<!-- 测试报告-->
<copy todir="${jmeter.result.html.dir}">
<fileset dir="${jmeter.home}/extras">
<include name="collapse.png"/>
<include name="expand.png"/>
</fileset>
</copy>
</target>
</project>
通过分析上面的build.xml文件,发现构建脚本由includes的值来定义,如果值为“*.jmx”,则会构建dir目录下所有的jmx文件。由于我们只需构建上传的脚本,那有必要修改build文件,使includes的值等于上传的脚本名称。
<testplans dir="D:\tools\PerformanceTesting\Jmeter_influxdb_grafana\apache-jmeter-3.1\TestCase\jenkins_jobworkspace" includes="测试.jmx"/>
修改build文件的includes值:
public static void modifyBuild(String filePath,String modifyName) throws ParserConfigurationException, IOException, SAXException {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new File(filePath)); // 读取xml文件
NodeList targetList = doc.getElementsByTagName("testplans"); //获取testplans节点
for (int i = 0; i < targetList.getLength(); i++) {
Node case_node = targetList.item(i); // 第一个caseNo节点
Element elem0 = (Element) case_node; // caseNo节点对象
String target_name = elem0.getAttribute("includes");
System.out.println("修改前includes = " + target_name); // 节点属性
elem0.setAttribute("includes",modifyName);
String target_name1 = elem0.getAttribute("includes");
System.out.println("修改后includes = " + target_name1); // 节点属性
}
saveXml(filePath, doc);
}
至此,第一阶段的工作已完成。当然,你也可以通过Git bash来push脚本触发构建,但是你得另外想办法来控制脚本的构建,因为Ant是根据build.xml文件来指定构建哪些脚本的。
<testplans dir="D:\tools\PerformanceTesting\Jmeter_influxdb_grafana\apache-jmeter-3.1\TestCase\jenkins_jobworkspace" includes="测试.jmx"/>
注意下图的Targets需同build.xml文件一致。
<target name="run">
<antcall target="test"/>
<!--性能脚本构建时,生成报告时间太长,注释掉 -->
<!-- antcall target="report"/ -->
</target>
由于依赖webhook来监听push事件触发构建,拷贝下图的URL,并在“高级”选项中生成“Secret token”,后续在gitlab添加webhook。
如果不想使用Secret token配置webhook,也可按以下方式来配置: 打开jenkins的“设置”页面,找到API Token,然后在gitlab上添加webhook url即可,结构如下图2所示(UserId:APIToken@jenkins构建器url)。
Influxdb+Grafana+Telegraf在笔者的另一篇文章<Jmeter排忧解难—性能测试监控>有提及,百度也大把文章,此处不再详述。
使用jmeter编写一个简单的测试脚本来进行测试,主要依赖Backend Listener监听器来集成influxdb。
运行“一、脚本上传小工具开发”提及的压测小工具,就可以对性能结果做实时监控了。最终实现效果图如下所示。
登录jenkins,可以查看详细的构建日志。