> 一小个题外话:一开始使用jmeter的目的是做接口测试,后来随着学习的深入发现jmeter是如此强大的一个工具,其自由定制和灵活程度完全不亚于现在主流的框架(比如用testng做接口这类的)。学习也有一段时间了,项目也终于用起来了,所以针对前阵子的学习做个总结,也好久没写博客了 -.-
(懒人就抄了百度百科了)
> JMeter的作用
1.能够对HTTP和FTP服务器进行压力和性能测试, 也可以对任何数据库进行同样的测试(通过JDBC)。
2.完全的可移植性和100% 纯java。
3.完全 Swing 和轻量组件支持[预编译的JAR使用 javax.swing.*)包。
4.完全多线程 框架允许通过多个线程并发取样和 通过单独的线程组对不同的功能同时取样。
5.精心的GUI设计允许快速操作和更精确的计时。
6.缓存和离线分析/回放测试结果。
JMeter的高可扩展性
1.可链接的取样器允许无限制的测试能力。
2.各种负载统计表和可链接的计时器可供选择。
3.数据分析和可视化插件提供了很好的可扩展性以及个性化。
4.具有提供动态输入到测试的功能(包括Javascript)。
5.支持脚本编程的取样器(在1.9.2及以上版本支持BeanShell)。
差不多就是这些特性了,接下来就都是这些特性的使用,这里先放一下我在项目接口中实现脚本后的部分截图,后续的实例可都是从实际项目中来的,请期待:
那么用过fiddler的同学因为都知道基本原理,jemeter基本上一样,核心就是中间代理。
中间代理可以录制一些访问的脚本,拿到脚本后再通过jemeter模拟线程并发访问网络,实现压力测试或者接口测试。
直接百度jemeter第一个就是下载连接了,点开进去下载发现有两个东西
上面是就是jmeter的客户端,下面是源码,正常使用下载上面就行了,那么源码是用来干什么的呢?最大的一个作用是支持自己写自定义协议的sample,属于比较高大上的用法了。
下下来其实就是一个压缩包,解压就能使用了,当然前提是你的电脑安装了jdk1.8版本,这个不在这里讨论的范围了。
需要注意的一点是,这个压缩包是通用的,因为是存java写的嘛,笔者就是直接拖到linux服务器运行的。
运行非常简单,window下直接运行bin目录下的bat文件就行了。重要是要介绍一下目录结构,这也和我们之后的工作关系比较大。
bin:运行的入口
docs:帮助文档,一堆e文
extras:生成报告的资源,里面有build.xml,用ant可以构建一个demo报告出来,同时还有一个ant-jmeter-1.1.1.jar,这个需要放在ant/lib目录下才能支持构建
lib:很重要的目录,之所以说jemeter强大,就在于它的扩展性,lib目录下是jmeter加载的所有jar包,所以包括自定义脚本和协议,都是加载这里面的类库的,里面的一堆取样器,都可以在里面找得到
lib/ext:自定义脚本打包成jar包,一般放这里面
作为一个测试应该都用过junit框架,junit的一个最基本的流程是@Before–>@Test–>@After。
那么jmeter也是类似的,不同的是写方法变成了添加可视化组件。
下面的图是建立在线程组之上的,jmeter的所有脚本都是运行在线程组内的,你可以理解成–新建一个测试类
我们可以看到这些可视化组件,我们以自动化思维的方式去分析这里的组件,不过先要知道执行顺序:
配置单元–前置处理器–逻辑控制器–定时器–取样器(Sampler)–后置处理器–断言–监听器
大概顺序就是这个样,当然这是在一个父类之下的元件执行顺序,下面我们分别理解它们到底是什么
配置单元:一般用来配置初始化的数据的,你可以理解成@BeforeClass或者设置全局变量
前置处理器:看成是@Before
逻辑控制器:就是逻辑语句,什么while…for…这些循环语句
定时器:类似sleep,计算等待,集合点
取样器(Sampler):就是我们的测试方法,jmeter弄成了对应协议的jar包,可以配置运行
后置处理器:就是@After,用得多的是jmeter的关联,简单的说就是下一个回包要用到上一个回包的结果,这个后面接口校验用的也比较多
断言–监听器:就是对结果的判断和报告了。
那么通过上面可以发现,基本和我们测试的思想是一致的:数据准备–执行测试–结果判断–生成报告。
有了上面的概念后我们直接上手了,界面的UI那些介绍就略过了。
要实现一个什么功能呢?
接口:https://www.sogou.com/web?query=cloud_huan
分析:
1.使用https访问
2.域名为www.sogou.com
3.路径为/web
4.get请求参数为query=cloud_huan
于是就考虑用配置单元创建一个https请求的默认值,里面写入一个通用的域名
然后新建一个http取样器,配置/web路径和get请求的参数
最后断言这个接口返回200,代表测试通过
所以总结起来步骤是这样的:
新建线程组–新建一个http取样器–为http取样器设置配置单元–为http取样器设置断言–为这个线程组加一个监听器
直接上源码(改为.jmx就可以使用)
<jmeterTestPlan version="1.2" properties="3.2" jmeter="3.2 r1790748">
<hashTree>
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="测试计划" enabled="true">
<stringProp name="TestPlan.comments">stringProp>
<boolProp name="TestPlan.functional_mode">falseboolProp>
<boolProp name="TestPlan.serialize_threadgroups">falseboolProp>
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="用户定义的变量" enabled="true">
<collectionProp name="Arguments.arguments"/>
elementProp>
<stringProp name="TestPlan.user_define_classpath">stringProp>
TestPlan>
<hashTree>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="线程组" enabled="true">
<stringProp name="ThreadGroup.on_sample_error">continuestringProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="循环控制器" enabled="true">
<boolProp name="LoopController.continue_forever">falseboolProp>
<stringProp name="LoopController.loops">1stringProp>
elementProp>
<stringProp name="ThreadGroup.num_threads">1stringProp>
<stringProp name="ThreadGroup.ramp_time">1stringProp>
<longProp name="ThreadGroup.start_time">1495620977000longProp>
<longProp name="ThreadGroup.end_time">1495620977000longProp>
<boolProp name="ThreadGroup.scheduler">falseboolProp>
<stringProp name="ThreadGroup.duration">stringProp>
<stringProp name="ThreadGroup.delay">stringProp>
ThreadGroup>
<hashTree>
<ConfigTestElement guiclass="HttpDefaultsGui" testclass="ConfigTestElement" testname="HTTP请求默认值" enabled="true">
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="用户定义的变量" enabled="true">
<collectionProp name="Arguments.arguments"/>
elementProp>
<stringProp name="HTTPSampler.domain">www.sogou.comstringProp>
<stringProp name="HTTPSampler.port">stringProp>
<stringProp name="HTTPSampler.protocol">httpsstringProp>
<stringProp name="HTTPSampler.contentEncoding">stringProp>
<stringProp name="HTTPSampler.path">stringProp>
<stringProp name="HTTPSampler.concurrentPool">6stringProp>
<stringProp name="HTTPSampler.connect_timeout">stringProp>
<stringProp name="HTTPSampler.response_timeout">stringProp>
ConfigTestElement>
<hashTree/>
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="搜狗搜索" enabled="true">
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="用户定义的变量" enabled="true">
<collectionProp name="Arguments.arguments">
<elementProp name="query" elementType="HTTPArgument">
<boolProp name="HTTPArgument.always_encode">falseboolProp>
<stringProp name="Argument.value">cloud_huanstringProp>
<stringProp name="Argument.metadata">=stringProp>
<boolProp name="HTTPArgument.use_equals">trueboolProp>
<stringProp name="Argument.name">querystringProp>
elementProp>
collectionProp>
elementProp>
<stringProp name="HTTPSampler.domain">stringProp>
<stringProp name="HTTPSampler.port">stringProp>
<stringProp name="HTTPSampler.protocol">stringProp>
<stringProp name="HTTPSampler.contentEncoding">stringProp>
<stringProp name="HTTPSampler.path">webstringProp>
<stringProp name="HTTPSampler.method">GETstringProp>
<boolProp name="HTTPSampler.follow_redirects">trueboolProp>
<boolProp name="HTTPSampler.auto_redirects">falseboolProp>
<boolProp name="HTTPSampler.use_keepalive">trueboolProp>
<boolProp name="HTTPSampler.DO_MULTIPART_POST">falseboolProp>
<stringProp name="HTTPSampler.embedded_url_re">stringProp>
<stringProp name="HTTPSampler.connect_timeout">stringProp>
<stringProp name="HTTPSampler.response_timeout">stringProp>
HTTPSamplerProxy>
<hashTree>
<ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="响应断言" enabled="true">
<collectionProp name="Asserion.test_strings">
<stringProp name="49586">200stringProp>
collectionProp>
<stringProp name="Assertion.test_field">Assertion.response_codestringProp>
<boolProp name="Assertion.assume_success">falseboolProp>
<intProp name="Assertion.test_type">2intProp>
ResponseAssertion>
<hashTree/>
hashTree>
<ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="察看结果树" enabled="true">
<boolProp name="ResultCollector.error_logging">falseboolProp>
<objProp>
<name>saveConfigname>
<value class="SampleSaveConfiguration">
<time>truetime>
<latency>truelatency>
<timestamp>truetimestamp>
<success>truesuccess>
<label>truelabel>
<code>truecode>
<message>truemessage>
<threadName>truethreadName>
<dataType>truedataType>
<encoding>falseencoding>
<assertions>trueassertions>
<subresults>truesubresults>
<responseData>falseresponseData>
<samplerData>falsesamplerData>
<xml>truexml>
<fieldNames>truefieldNames>
<responseHeaders>falseresponseHeaders>
<requestHeaders>falserequestHeaders>
<responseDataOnError>falseresponseDataOnError>
<saveAssertionResultsFailureMessage>truesaveAssertionResultsFailureMessage>
<assertionsResultsToSave>0assertionsResultsToSave>
<bytes>truebytes>
<sentBytes>truesentBytes>
<threadCounts>truethreadCounts>
<idleTime>trueidleTime>
<connectTime>trueconnectTime>
value>
objProp>
<stringProp name="filename">stringProp>
ResultCollector>
<hashTree/>
hashTree>
hashTree>
<WorkBench guiclass="WorkBenchGui" testclass="WorkBench" testname="工作台" enabled="true">
<boolProp name="WorkBench.save">trueboolProp>
WorkBench>
<hashTree/>
hashTree>
jmeterTestPlan>