说到接口我们都能想到 jmeter 这个工具,但是我们如何借助 jenkins 来做可持续集成自动化的测试呢?下面就是我对 jenkins、maven、jmeter 做的可持续化集成环境搭建的学习心得。

一,jmeter 脚本录制

这一步就是录制 Jmeter 脚本,确保脚本能正确运行。

二,建立一个 maven 工程

1,打开 eclipse,点击 File->New->Project->Maven Project

jenkins 执行jmeter脚本时的配置 jmeter和jenkins集成_apache

2,创建 maven 工程后,在工程目录下新建所需的文件夹

--Src/test/resources --存放报告模板文件
--src/main/
--src/test/jmeter --存放 jmeter 脚本文件跟一些接口调用的参数
--target/jmeter/bin --target 存放结果的根目录
--target/jmeter/html
--target/jmeter/html1
--target/jmeter/lib
--target/jmeter/logs
--target/jmeter/results
--target/maven-archiver
--target/surefire

jenkins 执行jmeter脚本时的配置 jmeter和jenkins集成_maven_02

3,编辑 pom.xml 文件

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
4.0.0
testDemo
bluemoon
1.11
bluemoon Maven Webapp
http://maven.apache.org
junit
junit
3.8.1
test
javax.servlet
servlet-api
3.0-alpha-1
mysql
mysql-connector-java
5.1.13
${project.build.directory}\jmeter\results
${project.build.directory}\jmeter\html
${project.build.directory}\jmeter\html1
TestReport
Codehaus repository
http://repository.codehaus.org/
true
always
true
always
bluemoon
com.lazerycode.jmeter
jmeter-maven-plugin
1.10.0
xml
true
flase
test
verify
jmeter
maven-compiler-plugin
1.6
1.6
UTF-8
src\test\jmeter\lib
org.codehaus.mojo
xml-maven-plugin
1.0-beta-3
verify
transform
src\test\resources\jmeter-results-detail-report_21.xsl
${jmeter.result.html.dir}
implementation="org.codehaus.plexus.components.io.filemappers.FileExtensionMapper">
html
src\test\resources\jmeter.results.shanhe.me.xsl
${jmeter.result.html.dir1}
implementation="org.codehaus.plexus.components.io.filemappers.FileExtensionMapper">
html
org.apache.maven.plugins
maven-dependency-plugin
copy-dependencies
prepare-package
copy-dependencies
${project.build.directory}/jmeter/lib
false
false
true
org.apache.maven.plugins
maven-jar-plugin
true
lib/
theMainClass
clean

4,调试工程,确保工程能正常运行

三,安装 jenkins 跟一些必要的插件

1,下载对应 windows 安装的 jenkins

2,安装好 jenkins 后本地启动 jenkins,进入插件管理界面,国内由于被墙了,所以需要配置一下。系统管理->管理插件->

3,需要安装的插件

Maven Integration plugin Maven 插件

Performance plugin 性能报告插件

HTML Publisher plugin HTTP report 插件

Git plugin GIT 插件

4,插件安装好后,就可以新建一个项目了,这里我们选择构建一个 maven 项目,名称为 bluemoon

jenkins 执行jmeter脚本时的配置 jmeter和jenkins集成_java_03

选择 Git,输入 Git 服务器的 URL 地址,用户名跟密码

jenkins 执行jmeter脚本时的配置 jmeter和jenkins集成_java接口持续集成自动化_04

Build 选项中输入 pom.xml 文件路径

添加构建后操作,增加一个 Publish HTML reports,html directory to archive 为转译后 html 文件的保存路径,

index pages 为转译后的文件名称,report title 为 jenkins 中显示的标题

jenkins 执行jmeter脚本时的配置 jmeter和jenkins集成_apache_05

构建后操作还可以添加邮件服务模块,就是构建成功后会发送邮件通知,这里就不举例了。

5,点击应用,保存。这时就可以点击立即构建来触发构建功能了

jenkins 执行jmeter脚本时的配置 jmeter和jenkins集成_apache_06

6,Console putput 可以查看输入日志,方便构建时查看哪里出现的问题

jenkins 执行jmeter脚本时的配置 jmeter和jenkins集成_apache_07

7,构建成功后,我们就可以查看脚本运行后的结果,点击 performace 或 function 来查看

jenkins 执行jmeter脚本时的配置 jmeter和jenkins集成_java_08

这里可以看到生成的 html 在 jenkins 使用 html publisher 查看报告时,发现显示不美观,不全的现象,很多东西显示不了。

在查看官方文档后,这原来是安全问题所导致的。

Jenkins 安全默认是将以下功能都关闭了

1、javascript

2、html 上的内置插件

3、内置 css 或从其它站的 css

4、从其它站的图处

5、AJAX

我的网页使用的是 css,所以显示不全。

解决这个问题可以在 jenkins 系统管理中输入以下脚本运行,就可以解决这个问题了

System.setProperty("hudson.model.DirectoryBrowserSupport.CSP", "")

jenkins 执行jmeter脚本时的配置 jmeter和jenkins集成_maven_09

jenkins 执行jmeter脚本时的配置 jmeter和jenkins集成_java接口持续集成自动化_10

四,最终效果

jenkins 执行jmeter脚本时的配置 jmeter和jenkins集成_apache_11

jenkins 执行jmeter脚本时的配置 jmeter和jenkins集成_java接口持续集成自动化_12

五,遇到的其他一些问题

1、当我们 jmeter 脚本中要运用 jdbc 来连接数据库时,此时是需要 jdbc 驱动的,这里解决的办法就是在 dependecy 中增

加依赖,然后再把这个依赖包拷贝到 target 的 lib 库中,这样用于引用 jdbc 的 jar 包就放到了 lib 中,也就解决了找不到 jdbc

驱动的问题

mysql
mysql-connector-java
5.1.13
org.apache.maven.plugins
maven-dependency-plugin
copy-dependencies
prepare-package
copy-dependencies
${project.build.directory}/jmeter/lib
false
false
true
org.apache.maven.plugins
maven-jar-plugin
true
lib/
theMainClass

2、如下图中,报告中有写图标是没有显示出来的,造成这个问题的原因是我们用 jenkins 持续集成时把把代码拷到 target 工程中没有把相应的图标拷贝过去,那么我们只

要把这个图标拷贝过去不就可以解决了吗?答案是肯定的。

jenkins 执行jmeter脚本时的配置 jmeter和jenkins集成_apache_11

把这两个图标文件一起放到工程中的 src/test/resources 目录下,再在 pox 中添加以下插件即可

jenkins 执行jmeter脚本时的配置 jmeter和jenkins集成_maven_14

这里我在 pom 文件中添加了一个插件,代码如下:

maven-resources-plugin
copy-resources
compile
copy-resources
${project.build.directory}/jmeter/html
${basedir}/src/test/resources
true

3、这里还需要注意的一个地方就是,在 src/test/jmeter 目录下要添加一个 jmeter.proprtties 文件,这个文件可以从我们自己下载的 jmeter 解压包中 bin 中找到,然后修改文件中对应内容为如下:

jmeter.save.saveservice.data_type=true
jmeter.save.saveservice.label=true
jmeter.save.saveservice.response_code=true
# response_data is not currently supported for CSV output
jmeter.save.saveservice.response_data=true
# Save ResponseData for failed samples
jmeter.save.saveservice.response_data.on_error=false
jmeter.save.saveservice.response_message=true
jmeter.save.saveservice.successful=true
jmeter.save.saveservice.thread_name=true
jmeter.save.saveservice.time=true
jmeter.save.saveservice.subresults=true
jmeter.save.saveservice.assertions=true
jmeter.save.saveservice.latency=true
jmeter.save.saveservice.connect_time=true
jmeter.save.saveservice.samplerData=true
jmeter.save.saveservice.responseHeaders=true
jmeter.save.saveservice.requestHeaders=true
jmeter.save.saveservice.encoding=false
jmeter.save.saveservice.bytes=true
# Only available with HttpClient4
jmeter.save.saveservice.sent_bytes=true
jmeter.save.saveservice.url=true
jmeter.save.saveservice.filename=true
jmeter.save.saveservice.hostname=true
jmeter.save.saveservice.thread_counts=true
jmeter.save.saveservice.sample_count=true
jmeter.save.saveservice.idle_time=true

这里这样做的目的是在我们查看生成的 html 报告时不会出现没有 Request 跟 Response 内容的问题。

4、我还遇到过这么一个问题,就是我们有时候会用到 beanshell 脚本,而用到 beanshell 脚本的时候有可能会用到我们自己写的 jar 包。比如我用到一个自己写的获取时间的 jar,当时把这个 jar 包放到了下图目录下

jenkins 执行jmeter脚本时的配置 jmeter和jenkins集成_java_15

然后通过 maven-resources-plugin 插件把这个包拷贝到 jmeter/lib/ext 目录下当时出错的代码是这样的:

maven-resources-plugin
copy-resources-lib
compile
copy-resources
${project.build.directory}/jmeter/lib/ext
${basedir}/src/test/lib
true

我们的 jar 成功拷贝到 jemter/lib/ext 目录下了,但是执行 jmeter 脚本的时候却报错:

jorphan.reflect.ClassFinder: Can not open the jar D:/eclipse-workspace/vet/target/jmeter/lib/ext/getTime.jar invalid CEN header (bad signature) java.util.zip.ZipException: invalid CEN header (bad signature)
at java.util.zip.ZipFile.open(Native Method)
at java.util.zip.ZipFile.(Unknown Source)
at java.util.zip.ZipFile.(Unknown Source)
at java.util.zip.ZipFile.(Unknown Source)
at org.apache.jorphan.reflect.ClassFinder.findClassesInOnePath(ClassFinder.java:435)
at org.apache.jorphan.reflect.ClassFinder.findClasses(ClassFinder.java:289)
at org.apache.jorphan.reflect.ClassFinder.findClassesThatExtend(ClassFinder.java:264)
at org.apache.jorphan.reflect.ClassFinder.findClassesThatExtend(ClassFinder.java:196)
at org.apache.jmeter.engine.util.CompoundVariable.(CompoundVariable.java:71)
at org.apache.jmeter.engine.util.ValueReplacer.(ValueReplacer.java:44)
at org.apache.jmeter.engine.PreCompiler.(PreCompiler.java:52)
at org.apache.jmeter.engine.StandardJMeterEngine.run(StandardJMeterEngine.java:305)
at java.lang.Thread.run(Unknown Source)

此时百度说我拷贝的 jar 包可能出错,百思不得其解。最后找了一个 md5 校验工具,果不其然,md5 确实跟源文件的 md5 值不一致了。在差点要放弃的时候我把 maven-resources-plugin 插件中一个参数改成了 false。

${basedir}/src/test/lib

false

最后执行工程,问题得到解决。

5、最近又想起了一个问题,就是我们能不能在构建成功后,如果脚本中有些用例执行失败是否可以发送邮件通知呢?这个是肯定的,然后我这里也写了下怎么触发邮件通知。

首先我们需要配置下 jenkins 全局配置中的邮件通知这个插件,具体配置大概如下图:

jenkins 执行jmeter脚本时的配置 jmeter和jenkins集成_apache_16

jenkins 执行jmeter脚本时的配置 jmeter和jenkins集成_java_17

然后再到 job 设置中添加 publish performance test result report 插件,输入以下信息:

jenkins 执行jmeter脚本时的配置 jmeter和jenkins集成_java接口持续集成自动化_18

最后添加插件 Editable Email Notification

jenkins 执行jmeter脚本时的配置 jmeter和jenkins集成_maven_19

jenkins 执行jmeter脚本时的配置 jmeter和jenkins集成_maven_20

特别注意,这里用到了一个邮件模板,所以还需要在 jenkins 安装目录下创建一个 email-templates 目录,然后新建一个文件命名为 testy.template,并输入以下内容:

BODY, TABLE, TD, TH, P {
font-family:Verdana,Helvetica,sans serif;
font-size:11px;
color:black;
}
h1 { color:black; }
h2 { color:black; }
h3 { color:black; }
TD.bg1 { color:white; background-color:#0000C0; font-size:120% }
TD.bg2 { color:white; background-color:#4040FF; font-size:110% }
TD.bg3 { color:white; background-color:#8080FF; }
TD.test_passed { color:blue; }
TD.test_failed { color:red; }
TD.console { font-family:Courier New; }
" />
BUILD ${build.result ?: 'SUCCESSFUL'}
URL
${rooturl}${build.url}
Project:
${project.name}
Date:
${it.timestampString}
Duration:
${build.durationString}
Cause:
 %> ${cause.shortDescription}


" />

BUILD ${build.result ?: 'SUCCESSFUL'}

URL

${rooturl}${build.url}

Project:

${project.name}

Date:

${it.timestampString}

Duration:

${build.durationString}

Cause:

%> ${cause.shortDescription}

if(changeSets != null) {
def hadChanges = false %>

CHANGES

cs_list.each() { cs ->
hadChanges = true %>
  Revision 
  
 
cs.metaClass.hasProperty('changeNumber') ? cs.changeNumber : "" %> by
: 
(${cs.msgAnnotated})
 %>
  ${p.editType.name}${p.path} 
 
}
}
if(!hadChanges) { %>
No Changes 
 
if(artifacts != null && artifacts.size() > 0) { %>

BUILD ARTIFACTS

%>

${f}

try {
def mbuilds = build.moduleBuilds
if(mbuilds != null) { %>

BUILD ARTIFACTS

try {
mbuilds.each() { m -> %>
 
 ${m.key.displayName} 
 
def artifactz = mvnbld.artifacts
if(artifactz != null && artifactz.size() > 0) { %>
 %>
${f}
}
}
} catch(e) {
//we don't do anything
} %>
}catch(e) {
//we don't do anything
}
%>
try {
def cucumberTestResultAction = it.getAction("org.jenkinsci.plugins.cucumber.jsontestsupport.CucumberTestResultAction")
junitResultList.add(cucumberTestResultAction.getResult())
} catch(e) {
//cucumberTestResultAction not exist in this build
}
if (junitResultList.size() > 0) { %>

${junitResultList.first().displayName}

junitResult -> %>
 %>
 Name: ${packageResult.getName()} Failed: ${packageResult.getFailCount()} test(s), Passed: ${packageResult.getPassCount()} test(s), Skipped: ${packageResult.getSkipCount()} test(s), Total: ${packageResult.getPassCount()+packageResult.getFailCount()+packageResult.getSkipCount()} test(s) 
 
 %>
 
 Failed: ${failed_test.getFullName()}  
 
}
} %>
} %>
CONSOLE OUTPUT

CONSOLE OUTPUT

%>

${org.apache.commons.lang.StringEscapeUtils.escapeHtml(line)}


最终邮件截图:

jenkins 执行jmeter脚本时的配置 jmeter和jenkins集成_java_21

mark 下谢谢!