💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
[toc] 属性扩展可以用来在属性值、请求正文、脚本等位置插入可变内容(即动态内容)。本节将介绍如何自己手写属性扩展,另外,你也可以通过可视化界面 [Get Data](GetData对话框.md) 对话框来辅助生成属性扩展。 # 语法 一个典型的属性扩展语法: ``` ${#Scope#Property-Name} ``` 包括更多参数的完整语法: ``` ${#Scope#Property-Name[::DataSource-Row][#Path-Expression]} ``` 其中: **Scope(作用域)** 属性的所属范围,如 `#Project#` ,`#TestCase#` 等等。 完整的可用作用域列表请参考 [这里](#scope-parameter-values) 。 **Property-Name(属性名称)** 期望属性的名称。 **DataSource-Row(数据源行号)** 可选。用于和数据源属性(列)有关的属性扩展。如果你的测试在每次迭代时获取的是多行数据,你可以使用这个参数来指定需要的某一行,例如: ``` ${DataSouceTestStep#MyProperty::1} ``` 索引从零开始。上面的示例中,获取的是某次迭代所返回数据集中的第二行。 如果要指定每次迭代返回的行数,在测试步骤 [DataSource](DataSource.md) 的设置中修改 **Row Per Iteration** 选项的值。请注意,**DataSource-Row** 的最大值应该小于测试步骤 DataSource 设置中 **Row Per Iteration** 选项的值。 更多用法请参考示例:[获取指定行的属性值](DataSource.md) 。 **Path-Expression(路径表达式)** 可选。用于提取 XML 或 JSON 数据。为了从 XML 或 JSON 内容中获取指定的值,需要给出对应的 XPath 或 JSONPath 表达式。 >[warning] ReadyAPI 无法解析包含了 byte order mark(BOM) 字符的 XML 文档 ***<span id="scope-parameter-values">作用域参数值</span>*** | 作用域 | 描述 | 示例 | | --- | --- | --- | | #Project# | 项目属性。 | ${#Project#Project property} | | #TestSuite# | 当前位置的测试套件(测试用例集)属性。 | ${#TestSuite#Suite property} | | #TestCase# | 当前位置的测试用例属性。 | ${#TestCase#Case property} | | TestStep# | 当前用例下的测试步骤名称。 | ${REST Request#Response} | | #[TestSuite#TestCase#TestStep]# | 为了引用其他测试套件或测试用例的属性,使用完整路径来指定期望的作用域。<br>路径被包裹在中括号里:<br>${#[Suite name#Case name#Step name]#Property name} | ${#[Shared suite#Common]#Username} | | #Global# | 全局属性。<br> **提示:** 你可以忽略该作用域。 | ${#Global#Global Property} <br> 或 <br> ${Global Property} | | #System# | 系统属性。 <br> **提示:** 点击菜单 **Help** > **System properties** 查看可用的系统属性。 | ${#System#os.name} | | #Env# | 系统环境变量。 | ${#Env#JAVA_HOME} | | #MockService# | 在虚拟服务中声明的属性。<br>**提示:** 该作用域仅在 [ServiceV](ServiceV.md) 中可用。 | ${#MockService#virt-service-property} | | #MockResponse# | 在虚拟响应中声明的属性。<br>**提示:** 该作用域仅在 [ServiceV](ServiceV.md) 中可用。 | ${#MockResponse#Response Property} | | #SecurityTest# | 在安全测试中声明的属性。<br>**提示:** 该作用域仅在 [Secure](Secure.md) 中可用。 | ${#SecurityTest#Secure Property} | # 动态表达式 动态属性是属性扩展的一种形式,通过插入 [Groovy](http://book.qadoc.org/groovy) 脚本提供动态数据。如果要在属性扩展中加入 Groovy ,使用下面的语法: ``` ${=Groovy code} ``` 下面的表达式生成了一个 0 到 999 之间的随机数: ``` ${=(int)(Math.random()*1000)} ``` 根据使用属性扩展的场景,你可以使用相关脚本对象。比如,在 [request](测试步骤.md) 测试步骤中,你可以使用 `request` 对象: >[success]`${=request.name}` 表达式计算结果为该 request 测试步骤的名称。 `${=request.operation.interface.project.name}` 表达式的计算结果为项目名称。 几乎在任何脚本中,都可以使用 `log` 对象。 在属性扩展表达式中使用第三方 Jar 包中的类,需要先导入: ``` def b = context.expand('${=import testa.Person;def a = new Person();a.say()}') ``` 运行结果: ![m1/TOIMGe6dd10701115055N.jpg](https://img.liyunx.com/m1/TOIMGe6dd10701115055N.jpg) # 嵌套属性扩展 你可以在另一个表达式中使用属性扩展。 **引用一个包含其他属性扩展的属性:** <table class="aqTable" cellspacing="0" cellpadding="0"> <thead> <tr style="background-color: #eee;"> <th class="aqTableHeader">属性</th> <th class="aqTableHeader">值</th> <th class="aqTableHeader">计算结果</th> </tr> </thead> <tbody> <tr> <td><span style="color : orange; ">PropertyA</span></td> <td>Hello!</td> <td>Hello!</td> </tr> <tr> <td><span style="color : red; ">PropExp</span></td> <td><code><span style="color : orange; ">${#TestCase#PropertyA}</span></code></td> <td>Hello!</td> </tr> <tr> <td>Result</td> <td><code><span style="color : red; ">${#TestCase#PropExp}</span></code></td> <td>Hello!</td> </tr> </tbody> </table> **属性扩展作为表达式的一部分:** <table class="aqTable" cellspacing="0" cellpadding="0"> <thead> <tr> <th class="aqTableHeader">属性</th> <th class="aqTableHeader">值</th> <th class="aqTableHeader">计算结果</th> </tr> </thead> <tbody> <tr> <td>PropA</td> <td>Hello!</td> <td>Hello!</td> </tr> <tr> <td>PropB</td> <td>Good Morning!</td> <td>Good Morning!</td> </tr> <tr> <td><span style="color : blue; ">PropName</span></td> <td>PropA</td> <td>PropA</td> </tr> <tr> <td>Result</td> <td><code>${#TestCase#<span style="color : blue; ">${#TestCase#PropName}</span>}</code></td> <td>Hello!</td> </tr> </tbody> </table> **使用属性扩展来指定 XPath 表达式:** <table class="aqTable" cellspacing="0" cellpadding="0"> <thead> <tr> <th class="aqTableHeader">属性</th> <th class="aqTableHeader">值</th> <th class="aqTableHeader">计算结果</th> </tr> </thead> <tbody> <tr> <td><span style="color : orange; ">xml</span></td> <td> <div class="aqCodeSegment"> <div id="IDDITF5MRGV313NJ2CQCEUPZU1RBW5F03U5XRQ5LHAGSCBK3RXJF_divcodeseg" class="aqCodeSegmentInternal"> <p>&lt;property&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;value id="123"&gt;Hello!&lt;/value&gt;<br> &lt;/property&gt;</p> </div> </div> </td> <td> <div class="aqCodeSegment"> <div id="IDPAJ3IFATKMTLK3DMUCTVAA5DLNON3V5FXHFDTTKRPUR2SJGQKOHC_divcodeseg" class="aqCodeSegmentInternal"> <p>&lt;property&gt;<br> &nbsp;&nbsp;&nbsp;&nbsp;&lt;value id="123"&gt;Hello!&lt;/value&gt;<br> &lt;/property&gt;</p> </div> </div> </td> </tr> <tr> <td><span style="color : red; ">id</span></td> <td>123</td> <td>123</td> </tr> <tr> <td><span style="color : blue; ">xpath</span></td> <td><code>//value[@id=<span style="color : red; ">${#TestCase#id}</span>]/text()</code></td> <td><code>//value[@id=<span style="color : red; ">123</span>]/text()</code></td> </tr> <tr> <td>Result</td> <td><code><span style="color : orange; ">${#TestCase#xml<span style="color : blue; ">#${#TestCase#xpath}</span>}</span></code></td> <td>Hello!</td> </tr> </tbody> </table> # 脚本中使用属性扩展 你可以在脚本中使用属性扩展。为了在 groovy 脚本中获取属性值,使用下面的语法: ``` def foo = context.expand( 'Property expansion' ) ``` 下面的代码片段将测试用例属性 *Username* 的值赋值给 foo 变量: ``` def foo = context.expand( '${#TestCase#Username}' ) ``` 当将属性扩展传递给 `context.expand()` 方法时,ReadyAPI 隐式地用属性扩展的计算结果替换属性扩展本身。假设上面示例中 *username* 属性的值为 `tester` ,得到的表达式如下: ``` def foo = context.expand( 'tester' ) ``` 同理,你可以通过连接字符串来构造更复杂的表达式: ``` // 假设测试用例有如下属性: // Username == tester // ID = 12345 def foo = context.expand ( '${#TestCase#Username} ${#TestCase#ID}' ) // 等价于 foo = context.expand('tester 12345') def foo = context.expand ( 'mynameis${#TestCase#Username}123' ) // 等价于 foo = context.expand('mynameistester123') ``` # 转义属性扩展 有时你可能需要传递属性扩展本身,而不是解析它。例如,你有一个包含多个属性扩展的数据源,并且想在后续的步骤中才解析这些扩展,而不是立即解析得到结果。 在这种情况下,你需要转义属性扩展。在属性扩展的开始位置添加一个额外的 `$` 符号,保证属性扩展不被解析。在测试运行期间,ReadyAPI 将移除第一个符号,并传递表达式的剩余部分。 比如,如果给出如下表达式: ``` $${#TestCase#Property} ``` ReadyAPI 将传递下面的表达式: ``` ${#TestCase#Property} ``` # 注意事项 属性扩展字符串不能使用双引号,因为 ${} 会被 Groovy 解析。 >[danger]错误示例: ``` def a = context.expand("${=(int)(Math.random()*1000)}"); ``` >[success]正确示例: ``` def a = context.expand('${=(int)(Math.random()*1000)}'); ``` 参考资料: 1、[ReadyAPI Documentation / Testing APIs / Using Properties / Property Expansion](https://support.smartbear.com/readyapi/docs/testing/properties/expansion.html) --- :-: --- 贡献者名单(排名不分先后) --- :-: **材料** :-: **编写** 李云 :-: **校验** :-: **支持**