JMX脚本组成分析
前言
在前两集,我们已经完成了项目与环境管理开发的实战。
通过观察E-R图,我们下一步的内容就是要去完成压测模块的内容,那么在完成压测模块的内容之前,我们要计划一下如何压测,以及要从哪个角度切入。
我计划压测引擎支持两种测试计划录入。
一个是本地上传JMX脚本,另一个是在线创建测试计划。
其中,我们应该好好研究一下本地上传JMX脚本应该如何进行。
研究以上内容,我们应该先从JMX脚本的组成出发,那么我们现在就开始对JMX脚本的组成进行分析。
JMX示例
JMX(JMeter Test Plan)脚本是 JMeter 中用来定义测试计划的文件,它以 .jmx
扩展名保存。
<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.6.3">
<hashTree>
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="测试计划">
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="用户定义的变量">
<collectionProp name="Arguments.arguments"/>
</elementProp>
</TestPlan>
<hashTree>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="线程组">
<intProp name="ThreadGroup.num_threads">5</intProp>
<intProp name="ThreadGroup.ramp_time">2</intProp>
<longProp name="ThreadGroup.duration">10</longProp>
<longProp name="ThreadGroup.delay">1</longProp>
<boolProp name="ThreadGroup.same_user_on_next_iteration">true</boolProp>
<boolProp name="ThreadGroup.scheduler">true</boolProp>
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="循环控制器">
<intProp name="LoopController.loops">-1</intProp>
<boolProp name="LoopController.continue_forever">false</boolProp>
</elementProp>
</ThreadGroup>
<hashTree>
<ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="查看结果树">
<boolProp name="ResultCollector.error_logging">false</boolProp>
<objProp>
<name>saveConfig</name>
<value class="SampleSaveConfiguration">
<time>true</time>
<latency>true</latency>
<timestamp>true</timestamp>
<success>true</success>
<label>true</label>
<code>true</code>
<message>true</message>
<threadName>true</threadName>
<dataType>true</dataType>
<encoding>false</encoding>
<assertions>true</assertions>
<subresults>true</subresults>
<responseData>false</responseData>
<samplerData>false</samplerData>
<xml>false</xml>
<fieldNames>true</fieldNames>
<responseHeaders>false</responseHeaders>
<requestHeaders>false</requestHeaders>
<responseDataOnError>false</responseDataOnError>
<saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
<assertionsResultsToSave>0</assertionsResultsToSave>
<bytes>true</bytes>
<sentBytes>true</sentBytes>
<url>true</url>
<threadCounts>true</threadCounts>
<idleTime>true</idleTime>
<connectTime>true</connectTime>
</value>
</objProp>
<stringProp name="filename"></stringProp>
</ResultCollector>
<hashTree/>
<ResultCollector guiclass="StatVisualizer" testclass="ResultCollector" testname="聚合报告">
<boolProp name="ResultCollector.error_logging">false</boolProp>
<objProp>
<name>saveConfig</name>
<value class="SampleSaveConfiguration">
<time>true</time>
<latency>true</latency>
<timestamp>true</timestamp>
<success>true</success>
<label>true</label>
<code>true</code>
<message>true</message>
<threadName>true</threadName>
<dataType>true</dataType>
<encoding>false</encoding>
<assertions>true</assertions>
<subresults>true</subresults>
<responseData>false</responseData>
<samplerData>false</samplerData>
<xml>false</xml>
<fieldNames>true</fieldNames>
<responseHeaders>false</responseHeaders>
<requestHeaders>false</requestHeaders>
<responseDataOnError>false</responseDataOnError>
<saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
<assertionsResultsToSave>0</assertionsResultsToSave>
<bytes>true</bytes>
<sentBytes>true</sentBytes>
<url>true</url>
<threadCounts>true</threadCounts>
<idleTime>true</idleTime>
<connectTime>true</connectTime>
</value>
</objProp>
<stringProp name="filename"></stringProp>
</ResultCollector>
<hashTree/>
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="HTTP请求">
<stringProp name="HTTPSampler.domain">127.0.0.1</stringProp>
<stringProp name="HTTPSampler.port">8082</stringProp>
<stringProp name="HTTPSampler.protocol">http</stringProp>
<stringProp name="HTTPSampler.path">/api/v1/test/login_form</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<stringProp name="HTTPSampler.method">POST</stringProp>
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
<boolProp name="HTTPSampler.postBodyRaw">false</boolProp>
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="用户定义的变量">
<collectionProp name="Arguments.arguments">
<elementProp name="mail" elementType="HTTPArgument">
<boolProp name="HTTPArgument.always_encode">false</boolProp>
<stringProp name="Argument.value">using</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
<boolProp name="HTTPArgument.use_equals">true</boolProp>
<stringProp name="Argument.name">mail</stringProp>
</elementProp>
<elementProp name="pwd" elementType="HTTPArgument">
<boolProp name="HTTPArgument.always_encode">false</boolProp>
<stringProp name="Argument.value">123456</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
<boolProp name="HTTPArgument.use_equals">true</boolProp>
<stringProp name="Argument.name">pwd</stringProp>
</elementProp>
</collectionProp>
</elementProp>
</HTTPSamplerProxy>
<hashTree/>
</hashTree>
</hashTree>
</hashTree>
</jmeterTestPlan>
上面这个例子可能有点大,所以大家可能要慢慢看。
分析
JMX 脚本的数据结构遵循 XML 格式,具有树状层次结构。下面是对您提供的 JMX 脚本数据结构的详细分析:
根元素
<jmeterTestPlan>
:这是 JMX 文件的根元素,包含了整个测试计划的所有信息。
一级子元素
<hashTree>
:作为根元素的直接子元素,用于组织和包含测试计划中的其他元素。
二级子元素
<TestPlan>
:定义了测试计划的基本信息,如版本和用户定义的变量。<ThreadGroup>
:定义了一组线程的属性,这些线程将执行测试中的请求。
三级子元素
<elementProp>
:在<TestPlan>
中,用于定义用户自定义的变量。<elementProp name="ThreadGroup.main_controller">
:在<ThreadGroup>
中,定义了循环控制器的属性。
四级子元素
<collectionProp>
:在<elementProp>
中,用于定义变量集合。<intProp>
、<longProp>
、<boolProp>
、<stringProp>
:在<ThreadGroup>
和<LoopController>
中,定义了线程组和循环控制器的各种属性。
五级子元素
<HTTPSamplerProxy>
:定义了一个 HTTP 请求的详细信息,如域名、端口、路径和请求方法。<ResultCollector>
:定义了结果收集器的属性和配置。
六级子元素
<objProp>
:在<ResultCollector>
中,定义了结果收集器的保存配置。<elementProp name="HTTPsampler.Arguments">
:在<HTTPSamplerProxy>
中,定义了 HTTP 请求的参数。
七级子元素
<value>
:在<objProp>
中,包含了结果收集器的详细保存配置。<collectionProp name="Arguments.arguments">
:在<elementProp name="HTTPsampler.Arguments">
中,包含了 HTTP 请求参数的集合。
八级子元素
<elementProp name="mail">
和<elementProp name="pwd">
:在<collectionProp>
中,定义了具体的请求参数及其属性。
属性
- 每个元素都有一系列的属性,这些属性定义了元素的具体行为和配置。例如:
name
:元素的名称。guiclass
、testclass
:与 JMeter GUI 相关的类信息。testname
:测试元素的显示名称。- 各种
Prop
(如intProp
、longProp
、boolProp
、stringProp
):定义了元素的配置参数。
特点
- 层次性:JMX 脚本具有清晰的层次结构,每个元素都可以包含子元素。
- 扩展性:可以通过添加新的元素和属性来扩展测试计划。
- 自描述性:元素的
guiclass
和testclass
属性提供了关于元素如何在 JMeter GUI 中表示的信息。 - 配置性:通过属性和子元素,可以详细配置每个组件的行为。
- 参数化:通过
<elementProp>
和<collectionProp>
,可以定义和使用参数,增加测试的灵活性。
这种数据结构的设计使得 JMX 脚本非常灵活,可以轻松地进行修改和扩展,以满足不同的测试需求。
JMX元素
总结一下,JMX 文件通常包含以下元素:
Test Plan: 这是测试脚本的主节点,所有的其他节点都应作为其子节点。
Thread Groups: 线程组定义了并发用户和他们的活动。每个线程组代表一组虚拟用户,他们并发执行预定的操作。
Samplers: Sampler是执行特定请求的节点,例如HTTP请求或JDBC请求等。这些请求产生对服务器的实际负载。
Controllers: 控制器节点决定JMeter如何组织和运行其测试计划中的请求。例如,使用“循环控制器”,在多个迭代中重复请求。
Listeners: 监听器节点用于收集和显示测试过程中的信息,如样本的结果、响应时间、吞吐量等。
Config Elements: 配置元素用于设置JMeter中的参数或属性。例设置cookie的HTTP Header Manager或定义用户定义的变量。
Assertions: 断言用于验证服务器响应是否符合预期。如果响应不符合预期,断言将标记样本为失败。
Pre-Processors, Post-Processors, and Assertions: 这些节点用于处理服务器响应或在发送请求之前设置请求的某些属性。