JMeter学习-007-JMeter 断言实例之一 - 响应断言

本文介绍如何使用JMeter进行响应断言和大小断言,并提供了一个具体的案例——易迅网App类目搜索的断言设置步骤及脚本示例。

之前的文章中已经对如何录制 web 的请求进行了详细的描述,敬请参阅:JMeter学习-004-WEB脚本入门实战

同时,我们的手机应用(例如:京东、天猫、唯品会、携程、易迅 等等 App)所发出的请求,也可进行录制,只需要将手机连接的无线网络代理到本机(以 iPhone 为例,依次点击 【设置】/【无线局域网】/【连接网络信息,即网络右侧详细信息符号】/【HTTP代理】/手动】,填写 服务器IP、端口 对应填写 JMeter 机器的 IP、JMeter HTTP 代理端口 即可),并将对应的端口设置为 JMeter 中设置的端口后,即可对相应的操作进行录制操作。非常简单,在此不再赘述。

当我们执行脚本的时候,需要依据一定的条件去判断脚本是否执行成功,例如响应信息(响应头、主体、响应数据、响应代码、大小等)、响应时间。JMeter 中也响应的给我们提供了相应的断言,大多数通用的断言 JMeter 均已给出,例如:Response Assertion、Size Assertion、MD5Hex Assertion等等。JMeter 提供的断言列表如下所示:

以下就以易迅网App的一个简单的类目搜索,对其添加响应断言和大小断言,来简单的演示一下 JMeter 中的断言。具体的操作步骤如下:

  1. 获取类目 手机数码-手机通讯-苹果 的 HTTP 请求(通过 JMeter HTTP代理服务器 录制即可获得,在此略)
  2. 添加如下所示 Response Assertion(前四)、Size Assertion(后一):
    1. 01 - 判断类目搜索结果状态码
    2. 02 - 判断类目搜索结果响应数据包含苹果
    3. 03 - 判断类目搜索结果中不包含信息
    4. 04 - 判断类目搜索结果响应头信息中包含 Server: nginx
    5. 05 - 判断响应结果大小(body)
  3. 添加查看结果树

添加响应断言:

右键单击 HTTP请求(手机数码-手机通讯-苹果),依次选择:【添加/断言/响应断言】,如下图所示:

响应断言添加页面如下所示:

要测试的响应字段:取样区域,也可简单理解为取样的数据源。单选 与 复选按钮可同时选择。

模式匹配规则:判断的关系依据。单选 与 复选按钮可同时选择,选择了复选框后,为前面关系条件的否。例如前面选择了 包括,同时勾选了 否,则实际判断关系依据为:不包括。

要测试的模式:可简单理解为判断的值。

PS:一个断言仅可判断一种类型的断言,无法混杂判断,即 要测试的响应字段、模式匹配规则、要测试的模式 在此断言中都是相同,若模式匹配规则不同,则需新增响应断言。

 

最终的脚本样式如下所示:

脚本源码为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
<? xml version="1.0" encoding="UTF-8"?>
< jmeterTestPlan version="1.2" properties="2.8" jmeter="2.13 r1665067">
   < hashTree >
     < TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="接口自动化测试用例 - 非登录态" enabled="true">
       < stringProp name="TestPlan.comments"></ stringProp >
       < boolProp name="TestPlan.functional_mode">false</ boolProp >
       < boolProp name="TestPlan.serialize_threadgroups">false</ boolProp >
       < 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="001-类目搜索验证" enabled="true">
         < stringProp name="ThreadGroup.on_sample_error">continue</ stringProp >
         < elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="循环控制器" enabled="true">
           < boolProp name="LoopController.continue_forever">false</ boolProp >
           < stringProp name="LoopController.loops">1</ stringProp >
         </ elementProp >
         < stringProp name="ThreadGroup.num_threads">1</ stringProp >
         < stringProp name="ThreadGroup.ramp_time">1</ stringProp >
         < longProp name="ThreadGroup.start_time">1419564228000</ longProp >
         < longProp name="ThreadGroup.end_time">1419564228000</ longProp >
         < boolProp name="ThreadGroup.scheduler">false</ boolProp >
         < stringProp name="ThreadGroup.duration"></ stringProp >
         < stringProp name="ThreadGroup.delay"></ stringProp >
       </ ThreadGroup >
       < hashTree >
         < HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="手机数码-手机通讯-苹果" enabled="true">
           < elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true">
             < collectionProp name="Arguments.arguments">
               < elementProp name="districtId" elementType="HTTPArgument">
                 < boolProp name="HTTPArgument.always_encode">false</ boolProp >
                 < stringProp name="Argument.name">districtId</ stringProp >
                 < stringProp name="Argument.value">29357</ stringProp >
                 < stringProp name="Argument.metadata">=</ stringProp >
                 < boolProp name="HTTPArgument.use_equals">true</ boolProp >
               </ elementProp >
               < elementProp name="exAppTag" elementType="HTTPArgument">
                 < boolProp name="HTTPArgument.always_encode">false</ boolProp >
                 < stringProp name="Argument.name">exAppTag</ stringProp >
                 < stringProp name="Argument.value">2045191607</ stringProp >
                 < stringProp name="Argument.metadata">=</ stringProp >
                 < boolProp name="HTTPArgument.use_equals">true</ boolProp >
               </ elementProp >
             </ collectionProp >
           </ elementProp >
           < stringProp name="HTTPSampler.domain">mb.51buy.com</ stringProp >
           < stringProp name="HTTPSampler.port"></ stringProp >
           < stringProp name="HTTPSampler.connect_timeout"></ stringProp >
           < stringProp name="HTTPSampler.response_timeout"></ stringProp >
           < stringProp name="HTTPSampler.protocol">http</ stringProp >
           < stringProp name="HTTPSampler.contentEncoding">GB2312</ stringProp >
           < stringProp name="HTTPSampler.path">/json.php?mod=Search&act=page&p=1&path=706188t706189&districtId=29357&areacode=1&dtype=list%7Cpage%7Cclasses&appSource=android&appVersion=45</ stringProp >
           < stringProp name="HTTPSampler.method">POST</ stringProp >
           < boolProp name="HTTPSampler.follow_redirects">true</ boolProp >
           < boolProp name="HTTPSampler.auto_redirects">false</ boolProp >
           < boolProp name="HTTPSampler.use_keepalive">true</ boolProp >
           < boolProp name="HTTPSampler.DO_MULTIPART_POST">false</ boolProp >
           < boolProp name="HTTPSampler.monitor">false</ boolProp >
           < stringProp name="HTTPSampler.embedded_url_re"></ stringProp >
         </ HTTPSamplerProxy >
         < hashTree >
           < HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP信息头管理器" enabled="true">
             < collectionProp name="HeaderManager.headers">
               < elementProp name="Charset" elementType="Header">
                 < stringProp name="Header.name">Charset</ stringProp >
                 < stringProp name="Header.value">UTF-8</ stringProp >
               </ elementProp >
               < elementProp name="Content-Type" elementType="Header">
                 < stringProp name="Header.name">Content-Type</ stringProp >
                 < stringProp name="Header.value">application/x-www-form-urlencoded</ stringProp >
               </ elementProp >
               < elementProp name="Accept-Encoding" elementType="Header">
                 < stringProp name="Header.name">Accept-Encoding</ stringProp >
                 < stringProp name="Header.value">gzip</ stringProp >
               </ elementProp >
               < elementProp name="User-Agent" elementType="Header">
                 < stringProp name="Header.name">User-Agent</ stringProp >
                 < stringProp name="Header.value">Dalvik/1.6.0 (Linux; U; Android 4.4.2; GT-I9502 Build/KOT49H)</ stringProp >
               </ elementProp >
             </ collectionProp >
           </ HeaderManager >
           < hashTree />
           < ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="01 - 判断类目搜索结果状态码" enabled="true">
             < collectionProp name="Asserion.test_strings">
               < stringProp name="71131476">"errno":0</ stringProp >
             </ collectionProp >
             < stringProp name="Assertion.test_field">Assertion.response_data</ stringProp >
             < boolProp name="Assertion.assume_success">false</ boolProp >
             < intProp name="Assertion.test_type">2</ intProp >
           </ ResponseAssertion >
           < hashTree />
           < ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="02 - 判断类目搜索结果响应数据包含苹果" enabled="true">
             < collectionProp name="Asserion.test_strings">
               < stringProp name="1065923">苹果</ stringProp >
             </ collectionProp >
             < stringProp name="Assertion.test_field">Assertion.response_data</ stringProp >
             < boolProp name="Assertion.assume_success">false</ boolProp >
             < intProp name="Assertion.test_type">2</ intProp >
           </ ResponseAssertion >
           < hashTree />
           < ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="03 - 判断类目搜索结果中不包含信息" enabled="true">
             < collectionProp name="Asserion.test_strings">
               < stringProp name="1425729940">我的博客地址: http://www.cnblogs.com/fengpingfan/</ stringProp >
             </ collectionProp >
             < stringProp name="Assertion.test_field">Assertion.response_headers</ stringProp >
             < boolProp name="Assertion.assume_success">false</ boolProp >
             < intProp name="Assertion.test_type">6</ intProp >
           </ ResponseAssertion >
           < hashTree />
           < ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="04 - 判断类目搜索结果响应头信息中包含 Server: nginx" enabled="true">
             < collectionProp name="Asserion.test_strings">
               < stringProp name="1066132337">Server: nginx</ stringProp >
             </ collectionProp >
             < stringProp name="Assertion.test_field">Assertion.response_headers</ stringProp >
             < boolProp name="Assertion.assume_success">false</ boolProp >
             < intProp name="Assertion.test_type">2</ intProp >
           </ ResponseAssertion >
           < hashTree />
           < SizeAssertion guiclass="SizeAssertionGui" testclass="SizeAssertion" testname="05 - 判断响应结果大小(body)" enabled="true">
             < stringProp name="Assertion.test_field">SizeAssertion.response_data</ stringProp >
             < stringProp name="SizeAssertion.size">4000</ stringProp >
             < intProp name="SizeAssertion.operator">3</ intProp >
           </ SizeAssertion >
           < hashTree />
         </ hashTree >
       </ hashTree >
       < ResultCollector guiclass="AssertionVisualizer" testclass="ResultCollector" testname="断言结果" enabled="true">
         < 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 >false</ fieldNames >
             < responseHeaders >false</ responseHeaders >
             < requestHeaders >false</ requestHeaders >
             < responseDataOnError >false</ responseDataOnError >
             < saveAssertionResultsFailureMessage >false</ saveAssertionResultsFailureMessage >
             < assertionsResultsToSave >0</ assertionsResultsToSave >
             < bytes >true</ bytes >
             < threadCounts >true</ threadCounts >
           </ value >
         </ objProp >
         < stringProp name="filename"></ stringProp >
       </ ResultCollector >
       < hashTree />
       < ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="察看结果树" enabled="true">
         < 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 >false</ fieldNames >
             < responseHeaders >false</ responseHeaders >
             < requestHeaders >false</ requestHeaders >
             < responseDataOnError >false</ responseDataOnError >
             < saveAssertionResultsFailureMessage >false</ saveAssertionResultsFailureMessage >
             < assertionsResultsToSave >0</ assertionsResultsToSave >
             < bytes >true</ bytes >
             < threadCounts >true</ threadCounts >
           </ value >
         </ objProp >
         < stringProp name="filename"></ stringProp >
       </ ResultCollector >
       < hashTree />
     </ hashTree >
   </ hashTree >
</ jmeterTestPlan >

脚本执行结果如下所示:

那么当断言失败的时候是什么样子呢?我们依据下两图进行相应的修改:

在此执行的结果如下图所示,通过点击对应的断言,可查看断言的详细信息:

当然您也可以添加断言结果(右键单击测试计划、线程组、HTTP请求,以此选择【添加/监听器/断言结果】添加即可,注意断言结果的作用域,避免出现干扰),通过断言结果更加直观的查看所有的失败断言汇总信息,如下所示:

 

我们可以利用 JMeter 提供的各种断言,进行请求响应结果的判定,其他在本文中没有用到的断言,各位小主们可先自行研究探索。同时,在实际的自动化应用过程中,JMeter 的断言难免出现不满足我们测试场景的时候,那么就需要我们针对不同的场景进行扩展了,通过已有断言 BeanShell 和 BSF 去进行扩展,也许可以解决我们的问题。另外,JMeter 是用 Java 语言编写的开源测试工具,当然也具有 Java 良好的扩展性,我们可以通过开发 JMeter 插件对其进行符合我们当前业务的定制扩展,以大大提升适应性、易用性。(PS:相关的简单实战示例,后续陆续更新,敬请期待!)

 

至此, JMeter学习-006-JMeter 断言实例之一 - 响应断言 顺利完结,希望此文能够给初学 JMeter 的您一份参考。

最后,非常感谢亲的驻足,希望此文能对亲有所帮助。热烈欢迎亲一起探讨,共同进步。非常感谢! ^_^

<think>首先,用户的问题是:“我想查找Jmeter响应断言中JSON断言的案例 请问Jmeter响应断言中JSON断言的案例”。用户正在询问关于JMeter中JSON断言的案例。 从系统指令中,我需要: - 使用中文回答。 - 结构清晰,帮助用户逐步解决问题。 - 保证回答真实可靠。 - 在回答中引用的段落末尾自然地添加引用标识,如[^1]。 - 最后生成相关问题。 - 对于数学表达式,使用$...$或$$...$$格式,但用户的问题是关于JMeter的,可能不涉及数学,所以我可以忽略这个部分,除非有相关内容。 用户提供的引用是关于JMeter断言的: - 引用[1]描述了响应断言的操作。 - 引用[2]解释了断言的目的。 - 引用[3]给出了一个JSONPath的实例- 引用[4]展示了一个接口响应体的例子。 - 引用[5]详细说明了JSON提取器和断言的操作。 用户明确提到了“Jmeter响应断言中JSON断言的案例”,所以我需要提供JSON断言的案例。 关键点: - JSON断言JMeter中用于检查JSON响应是否符合预期。 - 案例应该基于用户提供的引用,特别是引用[3]和[4],因为它们包含JSON示例。 从引用[3]: - 有一个JSON示例:一个书店的JSON数据。 - 它提到了JSONPath实例,如"$.store.book[0].author"等。 从引用[4]: - 有一个接口响应体的示例:包含status、message、data等字段。 我可以构建一个基于这些的案例。 结构化回答: 1. **介绍JSON断言**:简要解释JSON断言是什么,基于引用[2]。 2. **提供一个案例**:使用引用[3]或[4]中的JSON数据,展示如何在JMeter中设置JSON断言。 3. **步骤说明**:清晰描述添加JSON断言的过程。 4. **添加引用标识**:在相关部分末尾添加引用标识。 5. **生成相关问题**:在最后添加相关问题。 案例构建: - 使用引用[4]的JSON示例,因为它更简单直接。 ``` { "status": 200, "message": "success", "data": { "eid": 3, "name": "小新3", "limit": 1002, "status": true, "address": "某某会展中心103", "start_time": "2023-08-22T14:20:00" } } ``` - 假设我们要断言status为200,或者data中的某个字段。 JSON断言的设置步骤(基于引用[5]): - JMeter中,添加JSON断言元件。 - 设置JSON路径表达式。 - 期望值等。 确保回答真实可靠:基于提供的引用,不要添加虚构内容。 最终回答结构: - 开头:解释JSON断言- 主体:提供一个案例。 - 结尾:生成相关问题。 </think>### JMeter中JSON断言的案例解析 在JMeter中,JSON断言用于验证HTTP请求响应中的JSON数据是否符合预期。它基于JSONPath语法提取并检查特定字段的值,确保接口返回的数据正确无误。以下我将基于您提供的引用内容,逐步解释JSON断言的用法,并提供一个详细的案例。 #### 1. **JSON断言的基本概念** - JSON断言JMeter断言元件的一种,用于检查JSON响应体中的字段值或结构。例如,它可以验证`status`字段是否为200,或`data`中的一个嵌套字段是否匹配预期值[^2]。 - **核心设置参数**: - **JSON Path表达式**:指定要提取的JSON字段路径(如`$.data.eid`)。 - **期望值**:定义提取字段的预期结果(如`3`)。 - **Apply to**:通常设置为“Main sample only”,仅检查当前请求的响应[^5]。 - **断言类型**:可选择匹配规则(如“相等”或“包含”),默认基于JSONPath提取的值进行相等比较[^5]。 #### 2. **JSON断言案例:验证接口响应** 我们将使用引用[4]中的JSON响应体作为案例。假设这是一个用户信息接口的响应: ```json { "status": 200, "message": "success", "data": { "eid": 3, "name": "小新3", "limit": 1002, "status": true, "address": "某某会展中心103", "start_time": "2023-08-22T14:20:00" } } ``` **测试场景**:我们需要验证接口返回的`eid`(用户ID)是否为3,并且`status`字段为200。 **步骤-by-Step设置JSON断言**: 1. **在JMeter添加JSON断言**: - 右键点击HTTP请求 → 添加断言 → JSON断言- **Apply to**:选择“Main sample only”(默认)。 - **JSON Path表达式**:输入`$.data.eid`(提取`data`对象下的`eid`字段)。 - **Expected Value**:输入`3`(期望值)。 - **Match as regular expression?**:取消勾选(默认使用相等比较)。 - 点击“Add Assertion”添加更多检查项(可选)。 2. **添加第二个断言**(验证状态码): - 重复添加JSON断言元件。 - **JSON Path表达式**:输入`$.status`。 - **Expected Value**:输入`200`。 - 保存设置并运行测试。 3. **测试结果分析**: - 如果响应中`eid=3`且`status=200`,断言通过,测试标记为成功。 - 如果值不匹配(如`eid=4`),断言失败,JMeter会报告错误(例如在“View Results Tree”中显示失败详情)。 - **示例输出**:在断言成功后,您会看到类似“Assertion passed”的日志,确认数据正确[^2][^5]。 **为什么有效**:此案例直接基于真实接口响应(引用[4]),JSONPath语法`$.data.eid`提取了嵌套字段的值,并通过相等规则确保了数据准确性。类似地,您可扩展用于其他字段,如验证`message`是否为"success"[^3][^4]。 #### 3. **常见问题与技巧** - **JSONPath语法参考**:JSON断言依赖于JSONPath表达式的正确写法。例如: - `$`:根节点。 - `$.field`:提取顶级字段。 - `$.object.field`:提取嵌套对象字段。 - 引用[3]中的书店示例展示了更复杂的路径(如`$.store.book[0].author`),适用于数组处理[^3]。 - **调试建议**:使用“View Results Tree”元件预览响应,确认JSONPath表达式是否提取成功后再设置断言- **何时使用JSON断言**:适用于API测试中验证结构化JSON数据,避免仅依赖响应码(如200)而忽略数据错误[^2]。 通过这个案例,您可以快速上手JSON断言的应用。如果您有特定JSON响应或测试需求,我可以进一步定制示例。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值