自动化测试工具:TestHub V1.0.3 版本发布
自动化测试工具:TestHub V1.0.3 版本发布
简介
TestHub 是一款基于流程编排的自动化测试工具。是为了解决在软件开发旅程中测试流程管理和执行的复杂挑战而诞生的。传统测试工具可能局限于接口级自动化,无法满足多样化的需求,而我们在 TestHub 中引入了独特的流程编排功能,让您能够轻松定义、管理和执行测试流程。无论是自动化测试、流程调度还是其他自动化任务,TestHub 的插件式架构都能够满足您的无限扩展需求。
使用手册:http://nsrule.com/
演示环境:http://testhub.nsrule.com:11018/#/
Gitee 开源地址:https://gitee.com/dromara/TestHub
Gitub 开源地址:https://github.com/dromara/TestHub
演示视频:https://www.bilibili.com/video/BV1X94y1v7ak/
安装包:https://url37.ctfile.com/d/42659137-59604925-26bdd9?p=3710 (访问密码: 3710)
1.0.3 更新内容
-
🪲🪲 修复 BUG🪲🪲
-
优化用例编辑器卡顿问题
-
修复 HTTP 不支持异步接口能问题
-
自动生成的 ID 和人工输入的 ID 可能会产生重复@magic(感谢大佬) #I8AZW1
-
-
👍👍 新增功能 👍👍
如何使用 Formula 表达式
❓为什么要基于 antlr4 重构 Formula 表达式 ❓
ANTLR (ANother Tool for Language Recognition) 是一个强大的语法分析器生成工具,用于生成词法分析器和语法分析器。ANTLR4 是其最新版本,具有许多先进的功能,它有一些优势使其在一些情况下比TestHub之前版本手动解析更有优势,而且支持的语法更多。
Formula 表达式做为操作数是 TestHub 数据的最小操作单元,
我们用 FormulaNode 表示一个的操作数 - TestHub 中内置了 5 种基础操作数
-
DataNode 表示固定值,是有配置人员手动指定的, 例如:
xxxx
-
PathNode 表示变量值,可以基于 jsonPath 从决策上下文中获取指定的变量值,标识为
${xxx.yyy}
-
FuncNode 表示方法型函数的调用,标识为
%{方法名(形参 1:操作数,......)}
-
ArithmeticNode 表示计算算数运算, 例如:
1+2+3*4/5%3
-
MixNode 表示混合表达式
操作对象
后续介绍均以上下文中存在如下数据为前提
{ "store": { "book": [ { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 }, { "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99 }, { "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99 }, { "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "price": 22.99 } ], "bicycle": { "color": "red", "price": 19.95 } }, "expensive": 2 }
语法
固定值-DataNode
data="root"中的 我们写死的 root 其实就是 DataNode 类型的操作数
<param code="password" name = "密码" dataType="STRING" data="root"/>
写法 | 例子 | 值 |
---|---|---|
-1.0086 | 数字 | -1.0086 |
{attr:{a:1},attr1:1} | json 对象 | {"attr":{"a":1},"attr1":1} |
[${expensive},1] | 列表 操作对象的 expensive 做为第一个元素,1 是第二个元素 | [2,1] |
变量值-PathNode
::: warning PathNode 几乎支持了所有 jsonPath 的语法,但是我们不支持 $['store']['book'][0]['title']
这种[]
的写法 如果目前的语法满足不了你的测试过程,请于gitee
仓库提 lssues,我们会优先支持。 jsonPath 语法学习 请参考 https://github.com/alibaba/fastjson/wiki/JSONPath :::
写法 | 例子 | 值 |
---|---|---|
${expensive} | 操作对象的 expensive 的值 | 2 |
${store.book.price} | 操作对象的 store 的每一个 book 的 price 值 | [8.95, 12.99, 8.99, 22.99] |
${store.book[-1].author} | 操作对象的 store 的最后一个 book 的 author | J. R. R. Tolkien |
${store.book[0:2].author} | 操作对象的 store 的 0 到 2book 的 author | Nigel Rees,Sword of Honour,Herman Melville |
${store.book[?(isbn)]} | 操作对象的 store 的 book 中 isbn 属性不等于空的 | Herman Melville,J. R. R. Tolkien |
${store.book[author='Nigel Rees'].title} | 操作对象的 store 的 book 中 author 等于 Nigel Rees 的 book 的 title | Sayings of the Century |
内置方法-FuncNode
写法 | 例子 | 值 |
---|---|---|
%{getNowTime()} | 获取当前时间 | 看表 |
%{add(attr1:1,attr2:2)} | 进行 1+2 ,key:val 的写法 | 3 |
%{add(1,2)} | 进行 1+2 默认 key 为下标的写法 | 3 |
内置函数是我们基于 SPI 机制提供的扩展点之一,目前我们实现了这些内置函数
如果有不满足你的可以按照一下方式扩展
-
继承 FunctionHandler
package org.dromara.testhub.nsrule.core.executer.mode.base.function; import com.alibaba.fastjson.JSONObject; import org.dromara.testhub.nsrule.core.executer.context.Context; public interface FunctionHandler { String getName(); Object execute(Context context, JSONObject data); }
-
在 META-INF.services 路径下的 org.dromara.testhub.nsrule.core.executer.mode.base.function.FunctionHandler 配置的你扩展方法
算数运算-ArithmeticNode
是的我们支持了手写算数运算的表达式
符号 | 作用 |
---|---|
+ | 加 |
- | 减 |
* | 乘 |
/ | 除 |
% | 取余 |
() | 优先级 |
写法 | 例子 | 值 |
---|---|---|
1+2+3*4/5%3 | 计算1+2+3*4/5%3 | 5.4 |
1+(2+3)*4/5%3 | 计算1+(2+3)*4/5%3 | 2 |
混合表达式-MixNode
用户组合所有 FormulaNode 最终结果返回字符串
写法 | 例子 | 值 |
---|---|---|
http:${expensive}:10010/server/workerHeartbeat | 将操作对象的 expensive 的值替换后返回字符串 | http:2:10010/server/workerHeartbeat |
实践
<?xml version="1.0" encoding="UTF-8"?> <rule code="RULE_0000000013" name="Formula操作数使用说明" model="flow" project="default"> <actions> <action code="getData" name="操作数据" type="CONST" dataType="MAP"> <bound> {"store":{"book":[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99},{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}],"bicycle":{"color":"red","price":19.95}},"expensive":2} </bound> </action> </actions> <flows> <flow code="flow1"> <execute code="stp1" name="获取基础操作数据" actionCode="getData"/> <execute code="stp2" name="固定值-DataNode" actionCode="check"> <checkItem code="check1" name="固定值数字" msg=""> <expression expressionType="relation" operationCode="eq" dataType="NUMBER" cover="-1.0086" threshold="-1.0086"/> </checkItem> <checkItem code="check2" name="固定值字符串" msg=""> <expression expressionType="relation" operationCode="eq" dataType="STRING" cover="* 0/1 * * * ?" threshold="* 0/1 * * * ?"/> </checkItem> <checkItem code="check3" name="固定值列表" msg=""> <expression expressionType="relation" operationCode="eq" dataType="NUMBER" coverComplex="1" cover="[${stp1.expensive},1]" thresholdComplex="1" threshold="[2,1]"/> </checkItem> </execute> <execute code="stp3" name="变量值-PathNode" actionCode="check"> <checkItem code="check1" name="操作对象的 expensive 的值" msg=""> <expression expressionType="relation" operationCode="eq" dataType="NUMBER" cover="${stp1.expensive}" threshold="2"/> </checkItem> <checkItem code="check2" name="操作对象的 store 的每一个 book 的 price 值" msg=""> <expression expressionType="relation" operationCode="eq" dataType="STRING" coverComplex="1" cover="${stp1.store.book.price}" thresholdComplex="1" threshold="[8.95,12.99,8.99,22.99]"/> </checkItem> <checkItem code="check3" name="操作对象的 store 的最后一个 book 的 author" msg=""> <expression expressionType="relation" operationCode="eq" dataType="STRING" cover="${stp1.store.book[-1].author}" threshold="J. R. R. Tolkien"/> </checkItem> <checkItem code="check4" name="操作对象的 store 的 0 到 2book 的 author" msg=""> <expression expressionType="relation" operationCode="eq" dataType="STRING" coverComplex="1" cover="${stp1.store.book[0:2].author}" thresholdComplex="1" threshold="[Nigel Rees,Sword of Honour,Herman Melville]"/> </checkItem> <checkItem code="check5" name="操作对象的 store 的 book 中 isbn 属性不等于空的 的 author" msg=""> <expression expressionType="relation" operationCode="eq" dataType="STRING" coverComplex="1" cover="${stp1.store.book[?(isbn)].author}" thresholdComplex="1" threshold="[Herman Melville,J. R. R. Tolkien]"/> </checkItem> <checkItem code="check6" name="操作对象的 store 的 book 中 author 等于 Nigel Rees 的 book 的 title" msg=""> <expression expressionType="relation" operationCode="eq" dataType="STRING" cover="${stp1.store.book[author='Nigel Rees'].title}" threshold="Sayings of the Century"/> </checkItem> </execute> <execute code="stp4" name="内置方法-FuncNode" actionCode="check"> <checkItem code="check1" name="参数key:val形式" msg=""> <expression expressionType="relation" operationCode="eq" dataType="NUMBER" cover="%{add(attr1:1,attr2:2)}" threshold="3"/> </checkItem> <checkItem code="check2" name="参数,形式" msg=""> <expression expressionType="relation" operationCode="eq" dataType="NUMBER" cover="%{add(1,2)}" threshold="3"/> </checkItem> </execute> <execute code="stp5" name="算数运算-ArithmeticNode" actionCode="check"> <checkItem code="check1" name="计算1+2+3*4/5%3" msg=""> <expression expressionType="relation" operationCode="eq" dataType="NUMBER" cover="1+2+3*4/5%3" threshold="5.4"/> </checkItem> <checkItem code="check2" name="计算1+(2+3)*4/5%3" msg=""> <expression expressionType="relation" operationCode="eq" dataType="NUMBER" cover="1+(2+3)*4/5%3" threshold="2"/> </checkItem> </execute> <execute code="stp6" name="混合表达式-MixNode" actionCode="check"> <checkItem code="check1" name="store 的 book中第expensive+1个 的 author" msg=""> <expression expressionType="relation" operationCode="eq" dataType="STRING" cover="${stp1.store.book[%{add(${stp1.expensive},1)}].author}" threshold="J. R. R. Tolkien"/> </checkItem> <checkItem code="check2" name="store 的 book中第expensive+1个 的 author" msg=""> <expression expressionType="relation" operationCode="eq" dataType="STRING" cover="${stp1.expensive}.1" threshold="2.1"/> </checkItem> </execute> </flow> </flows> </rule>

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
腾讯 APIJSON 插件 apijson-query-spring-boot-starter 1.0.2
腾讯 APIJSON 是一种专为 API 而生的 JSON 网络传输协议 以及 基于这套协议实现的 ORM 库。为各种增删改查提供了完全自动化的万能 API,零代码实时满足千变万化的各种新增和变更需求。 能大幅降低开发和沟通成本,简化开发流程,缩短开发周期。适合中小型前后端分离的项目。 自 2016 年开源 7 年来发展迅速,目前 16K+ Star 位居 400W Java 开源项目前 100。 国内 腾讯、华为、阿里巴巴、字节跳动、美团、拼多多、百度、京东、网易、快手、圆通 等 和 国外 Google, Apple, Microsoft, Amazon, Tesla, Meta(FB), Paypal 等数百个知名大厂员工 Star, 也有 腾讯、华为、字节跳动、Microsoft、Zoom、知乎 等 工程师/专家/架构师 提了 PR/Issue, 还被 腾讯、华为、百度、SHEIN、快手、中兴、传音、圆通、美图 等各大知名厂商用于各类项目。 apijson-query-spring-boot-starter 1.0.1-1.0.2 更新内容: 返回结果使用驼峰规则转换; 修复l...
- 下一篇
Zulip Server 8.1 发布,开源团队协作工具
Zulip 是一个开源团队协作工具,一款专为实时和异步对话而设计的现代团队聊天应用程序,支持快速搜索、拖放文件上传、图像预览、组私人消息、可听通知、错过电子邮件消息提醒与桌面应用等。 Zulip Server 8.1 现已发布,一些更新内容包括: CVE-2024-21630:Zulip 版本 8.0 及其测试版存在一个错误,影响了不太可能的权限配置,其中某些用户角色有权创建可重用的邀请链接来加入组织,但缺乏订阅其他用户流的权限。具有此类角色的用户可能会错误地创建为新用户订阅流的邀请链接。此漏洞与 CVE-2023-32677 类似,但适用于多用户邀请,而不是单用户邀请。 修复了一个 fault-tolerance bug,即传出电子邮件身份验证失败可能会导致其他队列工作人员无法在低内存 Zulip 服务器上正常进行。 添加了对使用 PostgreSQL 16 作为数据库的支持。 已添加对明确停用移动推送通知注册的支持。 添加了对新类自定义身份验证 hook 的支持。 改进了向从其他聊天应用程序导入的用户发送密码重置电子邮件的工作流程。 改进了文件上传集成,以与使用不同 URL 寻址样...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS7设置SWAP分区,小内存服务器的救世主
- Mario游戏-低调大师作品
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- 2048小游戏-低调大师作品
- MySQL8.0.19开启GTID主从同步CentOS8