【AltWalker】模型驱动:轻松实现自动化测试用例的自动生成和组织执行
模型驱动的自动化测试
模型驱动的自动化测试(Model-Based Testing, 后文中我们将简称为MBT)是一种软件测试方法,它将系统的行为表示为一个或多个模型,然后从模型中自动生成和执行测试用例。这种方法的核心思想是将测试过程中的重点从手动编写测试用例转移到创建和维护描述系统行为的模型。
优势
基于MBT的测试相比较于普通的测试有以下几大优点:
| 优点 | 描述 |
|---|---|
| 覆盖率 | 模型是对系统行为的抽象表示,可以帮助测试人员更好地理解和分析系统的功能和性能。从而提高测试覆盖率。 |
| 测试效率 | 通过从模型中自动生成测试用例,减少手动编写测试用例的工作量,提高测试效率。 |
| 可维护性 | 模型驱动的测试用例易于维护,因为当系统发生变化时,只需更新模型,而无需手动修改大量测试用例。 |
| 可重用性 | 模型可以在多个测试项目中重用,减少重复工作并提高测试质量。 |
操作步骤
基于MBT的测试主要有以下几个步骤:
创建模型:
首先,需要构建一个描述系统行为的模型。这个模型通常采用图形表示,如状态机、Petri网或者流程图等。模型中的顶点表示系统的状态,边表示状态之间的转换。生成测试用例:
通过分析模型,可以自动生成测试用例。测试用例生成算法可以根据不同的目标(如覆盖率、路径长度等)来选择。常用的算法有随机测试、覆盖所有路径、覆盖所有边等。执行测试:
使用自动生成的测试用例对实际系统进行测试。这一步通常需要一个测试执行引擎,它可以将模型中的操作映射到实际系统中的操作。例如,使用Selenium WebDriver进行Web应用测试。验证结果:
比较实际系统的行为与模型的预期行为,以确定系统是否满足需求。如果发现问题,可以更新模型并重新生成测试用例。
下面我们一起来看看在实际业务中使用AltWalker库进行进行基于模型的自动化测试的应用。
什么是AltWalker?
AltWalker是一个基于图模型的自动化测试框架,用于编写、执行和管理基于模型的测试。它主要用于测试复杂系统,如Web应用程序、移动应用程序等。它支持运行用 .NET/C# 和 Python3 编写测试模型用例。
安装AltWalker
在命令行中输入以下命令来安装AltWalker:
pip install altwalker
检查是否安装了正确的版本
$ altwalker --version
AltWalker, version 0.3.1
牛刀小试
创建一个测试项目
创建一个新的文件夹,用于存放我们的测试项目。在该文件夹中,执行以下命令创建MBT:
altwalker init -l python test-project
执行这个命令后,将在当前目录生成一个包含模型模板代码的目录test-project,目录结构如下:
# tree
test-project/
├── models/
│ ├── default.json
└── tests/
├── __init__.py
└── test.py
运行测试
只需要执行以下命令,就能够运行default.json中定义的模型,覆盖模型的链路,链路执行时会运行对应在test.py中的代码:
$ cd test-project
$ altwalker online tests -m models/default.json "random(edge_coverage(100))"
运行效果

自己编写图模型
上面只是执行了一个单一的链路Demo,下面我们一起写一个我们自己的模型。
模型编辑器我们可以选择在线的,也可以选择使用 vscode的插件,当然也可以选择自己搭建一个。
在线模型编辑器
我们可以使用在线的模型编辑器来编写模型。
VScode扩展
可以在扩展上搜索AltWalker Model Visualizer
,也可以自己访问链接下载扩展来编辑查看模型。
本地部署
可以参考:https://github.com/altwalker/model-editor
包含登录、选择产品、支付、退出登录的模型编写
点击查看对应模型
{
"name": "Pay Models",
"models": [
{
"name": "PayModel",
"generator": "random(edge_coverage(100) && vertex_coverage(100))",
"startElementId": "v_init",
"vertices": [
{
"id": "v_init",
"name": "start_vertex"
},
{
"id": "v_login",
"name": "state_login"
},
{
"id": "v_select_product",
"name": "state_select_product"
},
{
"id": "v_pay",
"name": "state_pay"
},
{
"id": "v_logout",
"name": "state_logout"
}
],
"edges": [
{
"id": "e_init",
"name": "action_init",
"sourceVertexId": "v_init",
"targetVertexId": "v_login"
},
{
"id": "e_login",
"name": "action_login",
"sourceVertexId": "v_login",
"targetVertexId": "v_select_product"
},
{
"id": "e_select_product",
"name": "action_select_product",
"sourceVertexId": "v_select_product",
"targetVertexId": "v_pay"
},
{
"id": "e_pay",
"name": "action_pay",
"sourceVertexId": "v_pay",
"targetVertexId": "v_logout"
},
{
"id": "e_logout",
"name": "action_logout",
"sourceVertexId": "v_logout",
"targetVertexId": "v_init"
}
]
}
]
}
模型效果

1、校验模型
保存这个模型到新创建的项目default.json,然后执行下面的命令检查模型是否存在问题:
altwalker check -m models/default.json "random(never)"
2、验证测试代码是否和模型是否匹配
altwalker check -m models/default.json "random(never)"
因为我们还没有编写测试代码,所以会出现下面的报错:

可以看到在上面的报错中给出了建议的代码,我们把它复制到 test.py中。
class PayModel:
def state_pay(self):
pass
def action_init(self):
pass
def state_select_product(self):
pass
def state_logout(self):
pass
...
3、运行测试
在命令行中执行下面的命令来执行测试:
altwalker online tests -m models/default.json "random(edge_coverage(100))" --report-xml-file report.xml
这将会运行在default.json和test.py文件中定义的所有测试用例。
4、查看测试报告
在测试执行完成后,AltWalker会生成一个名为report.xml的JUnit格式的测试报告。我们可以使用任何支持JUnit格式的测试报告工具来查看这个报告。
还有其他方式的测试报告提供,可以查看官方文档。
一个比较复杂的例子
如果我们有一个商城需要验证,有登录、用户个人中心,商品首页,商品详情页、支付界面、订单界面等,我们要针对这样的网站做一个自动化,可能会有以下这些场景:
| 场景 |
|---|
| 登录界面 -> Do:输入密码登录 -> 用户首页 -> Do:查看商品A -> A商品详情页 -> Do:点击第二个商品按钮 -> 商品C详情页面 -> Do:点击付款 -> 付款界面 -> Do:取消付款 -> 订单倒计时界面 -> Do:关闭浏览器 -> 浏览器关闭 |
| 登录界面 -> Do:输入密码登录 -> 用户首页 -> Do:查看商品A -> A商品详情页 -> Do:点击第二个商品按钮 -> 商品C详情页面 -> Do:点击付款 -> 付款界面 -> Do:查看订单 -> 历史订单界面 -> Do:关闭浏览器 -> 浏览器关闭 |
| 登录界面 -> Do:输入密码登录 -> 用户首页 -> Do:查看商品A -> A商品详情页 -> Do:点击第二个商品按钮 -> 商品C详情页面 -> Do:点击付款 -> 付款界面 -> Do:查看订单 -> 历史订单界面 -> Do:查看订单详情 -> 订单详情界面 -> Do:关闭浏览器 -> 浏览器关闭 |
| 登录界面 -> Do:输入密码登录 -> 用户首页 -> Do:查看商品A -> A商品详情页 -> Do:点击第二个商品按钮 -> 商品C详情页面 -> Do:点击用户中心 -> 用户中心界面 -> Do:查看订单 -> 历史订单界面 -> Do:关闭浏览器 -> 浏览器关闭 |
| 登录界面 -> Do:输入密码登录 -> 用户首页 -> Do:查看商品A -> A商品详情页 -> Do:点击第二个商品按钮 -> 商品C详情页面 -> Do:点击用户中心 -> 用户中心界面 -> Do:查看订单 -> 历史订单界面 -> Do:查看订单详情 -> 订单详情界面 -> Do:关闭浏览器 -> 浏览器关闭 |
| 登录界面 -> Do:输入密码登录 -> 用户首页 -> Do:查看商品A -> A商品详情页 -> Do:点击相似商品B -> 商品B详情页 -> Do:点击购买 -> 付款界面 -> Do:取消付款 -> 订单倒计时界面 -> Do:关闭浏览器 -> 浏览器关闭 |
| 登录界面 -> Do:输入密码登录 -> 用户首页 -> Do:查看商品A -> A商品详情页 -> Do:点击相似商品B -> 商品B详情页 -> Do:点击购买 -> 付款界面 -> Do:查看订单 -> 历史订单界面 -> Do:关闭浏览器 -> 浏览器关闭 |
| 登录界面 -> Do:输入密码登录 -> 用户首页 -> Do:查看商品A -> A商品详情页 -> Do:点击相似商品B -> 商品B详情页 -> Do:点击购买 -> 付款界面 -> Do:查看订单 -> 历史订单界面 -> Do:查看订单详情 -> 订单详情界面 -> Do:关闭浏览器 -> 浏览器关闭 |
| ... |
使用 MBT 图示展示(箭头表示操作)

大家应该都能发现,使用altwalker画出来的图,能非常直观的展示各个页面之间可以进行的操作,并且很好扩展,这非常符合我们做页面自动化的时候所说的POM(Page Object Model)。
这也是altwalker最重要的价值所在:适合的用于测试复杂系统,如Web应用程序、移动应用程序等。
点击查看对应模型
{
"name": "Default Models",
"models": [
{
"name": "DefaultModel",
"generator": "random(never)",
"startElementId": "v0",
"vertices": [
{
"id": "v0",
"name": "登录界面"
},
{
"id": "v1",
"name": "用户首页"
},
{
"id": "v2",
"name": "浏览器关闭"
},
{
"id": "v3",
"name": "A商品详情页"
},
{
"id": "v6",
"name": "商品C详情页面"
},
{
"id": "v7",
"name": "付款界面"
},
{
"id": "v8",
"name": "付款成功界面"
},
{
"id": "v9",
"name": "订单倒计时界面"
},
{
"id": "v10",
"name": "用户中心界面"
},
{
"id": "v11",
"name": "商品B详情页"
},
{
"id": "v4",
"name": "历史订单界面"
},
{
"id": "v5",
"name": "订单详情界面"
}
],
"edges": [
{
"id": "e0",
"name": "输入密码登录",
"sourceVertexId": "v0",
"targetVertexId": "v1"
},
{
"id": "e1",
"name": "关闭浏览器",
"sourceVertexId": "v0",
"targetVertexId": "v2"
},
{
"id": "e2",
"name": "关闭浏览器",
"sourceVertexId": "v1",
"targetVertexId": "v2"
},
{
"id": "e3",
"name": "查看商品A",
"sourceVertexId": "v1",
"targetVertexId": "v3"
},
{
"id": "e5",
"name": "点击第二个商品按钮",
"sourceVertexId": "v3",
"targetVertexId": "v6"
},
{
"id": "e7",
"name": "点击付款",
"sourceVertexId": "v6",
"targetVertexId": "v7"
},
{
"id": "e8",
"name": "退出登录",
"sourceVertexId": "v8",
"targetVertexId": "v0"
},
{
"id": "e9",
"name": "e9",
"sourceVertexId": "v3",
"targetVertexId": "v8"
},
{
"id": "e10",
"name": "付款成功",
"sourceVertexId": "v7",
"targetVertexId": "v8"
},
{
"id": "e11",
"name": "取消付款",
"sourceVertexId": "v7",
"targetVertexId": "v9"
},
{
"id": "e12",
"name": "点击用户中心",
"sourceVertexId": "v6",
"targetVertexId": "v10"
},
{
"id": "e13",
"name": "点击购买",
"sourceVertexId": "v11",
"targetVertexId": "v7"
},
{
"id": "e14",
"name": "点击相似商品B",
"sourceVertexId": "v3",
"targetVertexId": "v11"
},
{
"id": "e17",
"name": "关闭浏览器",
"sourceVertexId": "v9",
"targetVertexId": "v2"
},
{
"id": "e18",
"sourceVertexId": "v10",
"targetVertexId": "v4",
"name": "查看订单"
},
{
"id": "e19",
"name": "点击首页按钮",
"sourceVertexId": "v3",
"targetVertexId": "v1"
},
{
"id": "e20",
"name": "点击首页",
"sourceVertexId": "v6",
"targetVertexId": "v1"
},
{
"id": "e21",
"name": "点击用户中心",
"sourceVertexId": "v10",
"targetVertexId": "v1"
},
{
"id": "e4",
"name": "刷新浏览器",
"sourceVertexId": "v6",
"targetVertexId": "v6"
},
{
"id": "e6",
"name": "查看订单",
"sourceVertexId": "v7",
"targetVertexId": "v4"
},
{
"id": "e15",
"name": "关闭浏览器",
"sourceVertexId": "v4",
"targetVertexId": "v2"
},
{
"id": "e16",
"name": "查看订单详情",
"sourceVertexId": "v4",
"targetVertexId": "v5"
},
{
"id": "e22",
"name": "关闭浏览器",
"sourceVertexId": "v5",
"targetVertexId": "v2"
}
],
"actions": [
"fasf;fdsaf;"
]
}
]
}
完整的结合 POM使用的方法可以查看官方给出的示例:https://github.com/altwalker/altwalker-examples
结合已有框架使用
如果我们仅仅只想使用模型中的链路组织能力,也可以自己根据编写的模型使用下面这段代码来生成对应的链路,然后组织用例场景,可以用于自动化用例生成。
graph_data = {
"name": "Default Models",
"models": [
{
"name": "DefaultModel",
"generator": "random(never)",
"startElementId": "v0",
"vertices": [
{
"id": "v0",
"name": "登录界面"
...
]
}
model = graph_data['models'][0]
edges = model['edges']
vertices = model['vertices']
start_vertex_id = model['startElementId']
# 构建图
graph = {}
for edge in edges:
source = edge['sourceVertexId']
target = edge['targetVertexId']
if source not in graph:
graph[source] = []
graph[source].append((target, edge['name']))
# 顶点ID到顶点名称的映射
vertex_name_map = {vertex['id']: vertex['name'] for vertex in vertices}
# 深度优先搜索
def dfs(_graph, start_vertex, _path, _visited):
_visited.add(start_vertex)
_path.append(vertex_name_map[start_vertex])
if start_vertex not in _graph:
print(" -> ".join(_path))
else:
for neighbor, action in _graph[start_vertex]:
if neighbor not in _visited:
_path.append(f"Do:{action}")
dfs(_graph, neighbor, _path, _visited)
_path.pop()
_path.pop()
_visited.remove(start_vertex)
# 打印所有可能的链路及其经过的操作,操作前面加上"Do"标记
visited = set()
path = []
dfs(graph, start_vertex_id, path, visited)
总结
通过以上步骤,我们了解了如何使用AltWalker进行模型驱动的自动化测试。AltWalker是一个强大的测试框架,可以帮助我们更高效地编写、执行和管理测试用例。
当然,基于模型的测试也有一些局限性,如模型的准确性和完整性对测试结果影响较大,模型构建和维护可能需要额外的成本等。因此,在实际应用中,需要根据项目的具体需求来决定是否采用基于模型的测试方法。希望本文对你有所帮助!
【AltWalker】模型驱动:轻松实现自动化测试用例的自动生成和组织执行的更多相关文章
- 自动的自动化:EvoSuite 自动生成JUnit的测试用例
EvoSuite简介 EvoSuite是由Sheffield等大学联合开发的一种开源工具,用于自动生成测试用例集,生成的测试用例均符合Junit的标准,可直接在Junit中运行.得到了Google和Y ...
- 自动化API之一 自动生成Mysql数据库的微服务API
本文演示如何利用Uniconnector平台,自动生成Mysql数据库的API,节约开发人员编写后台API的时间.使用生成API的前提是开发者有 自己的数据库,有数据库的管理权限,并能通过外网 ...
- Fitnesse测试用例脚本自动生成设计
Fitnesse是通过wiki形式来展示.管理和执行测试用例,若要在Fitnesse上设计测试用例,前提是必须熟悉一定的wiki语法,虽然wiki语法简单,但是若要设计成百上千的测试用例还是有很大的工 ...
- Groovy元编程应用之自动生成订单搜索接口测试用例集
背景 在 "Groovy元编程简明教程" 一文中,简明地介绍了 Groovy 元编程的特性. 那么,元编程可以应用哪些场合呢?元编程通常可以用来自动生成一些相似的模板代码. 在 & ...
- Python自动化测试用例设计--自动化测试用例与手工测试用例区别与联系
1. 前言 手工测试用例是针对手工测试人员,自动化测试用例是针对自动化测试框架,前者是手工测试用例人员应用手工方式进行用例解析,后者是应用脚本技术进行用例解析,两者最大的各自特点在于,前者具有较好的异 ...
- Asp.Net Core 轻松学系列-5利用 Swagger 自动生成接口文档
目录 前言 结语 源码下载 前言 目前市场上主流的开发模式,几乎清一色的前后端分离方式,作为服务端开发人员,我们有义务提供给各个客户端良好的开发文档,以方便对接,减少沟通时间,提高开发效率:对 ...
- airtest+poco多脚本、多设备批处理运行测试用例自动生成测试报告
一:主要内容 框架功能及测试报告效果 airtest安装.环境搭建 框架搭建.框架运行说明 airtest自动化脚本编写注意事项 二:框架功能及测试报告效果 1. 框架功能: 该框架笔者用来作为公司的 ...
- 如何统计自动化测试用例的ROI 【投入产出比/投资回报率】
一. 自动化测试的投入有哪些? 1. 自动化测试的软件平台投入 自动化测试平台的开发时间,实施时间. 2. 自动化测试的框架开发投入+框架维护的投入 开发自动化测试脚本使用的框架,例如通过一些现有框 ...
- python实战-基于正交实验(工具:allpairs)自动生成接口异常测试用例
实现思路 1.抓取api信息(目前公司用的swagger),uri.method.params.response,解析完成后写入excle 2.读取抓取完毕的api信息,处理为allpairs所需要的 ...
- 基于数据库的自动化生成工具,自动生成JavaBean、自动生成数据库文档等(v4.1.2版)
目录: 第1版:http://blog.csdn.net/vipbooks/article/details/51912143 第2版:htt ...
随机推荐
- react中super()的理解
首先 super() 是在 es6的class(类)的方法创建组件出现 下面是分别是构造函数创建组件和class(类)创建组件 构造函数方法创建组件 在构造函数方法中,在组件接收参数的时候,props ...
- OFFICE-Excel_在只有清单没有定额人材机的情况下筛选工程量的操作
目的 一个来自东莞的项目需要清单里面所有的电线电缆的量和价,但是由于东莞市的投标清单只需要清单报价即可,没有定额,也就没有人材机,所以就只能依靠清单来剔除量,但是有几个问题,众所周知电线电缆这种材料一 ...
- MySQL 中读写分离数据延迟
MySQL 中读写分离可能遇到的问题 前言 读写分离的架构 基于客户端实现读写分离 基于中间代理实现读写分离 MySQL 中如何保证主从数据一致 循环复制问题 主从同步延迟 主从同步延迟的原因 主从延 ...
- Python网页开发神器fac 0.2.8、fuc 0.1.28新版本更新内容介绍
fac项目地址:https://github.com/CNFeffery/feffery-antd-components fuc项目地址:https://github.com/CNFeffery/fe ...
- Vue中使用原生js实现轮播图滑动效果
1.在视图层模板里面绑定touchstart和touchend事件 <div class="tuWap" @touchstart="touchStart" ...
- 2022-08-16:绳子总长度为M, 100 -> M, (6, 100) (7,23) (10,34) -> arr, 每一个长度的绳子对应一个价格,比如(6, 10)表示剪成长度为6的绳子,对应
2022-08-16:绳子总长度为M, 100 -> M, (6, 100) (7,23) (10,34) -> arr, 每一个长度的绳子对应一个价格,比如(6, 10)表示剪成长度为6 ...
- 2022-03-14:一开始屏幕上什么也没有,粘贴板里什么也没有, 你只能在键盘上做如下4种操作中的1种: 输入:在屏幕上已经显示内容的后面加一个A, 全选:把屏幕上已经显示的全部内容选中, 复制:被
2022-03-14:一开始屏幕上什么也没有,粘贴板里什么也没有, 你只能在键盘上做如下4种操作中的1种: 输入:在屏幕上已经显示内容的后面加一个A, 全选:把屏幕上已经显示的全部内容选中, 复制:被 ...
- 2021-10-30:有效的字母异位词。给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位
2021-10-30:有效的字母异位词.给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词.注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位 ...
- TestForPicGo
如果显示,则为成功 否则,失败 同时为CN-BLOG的vscode插件进行测试
- JeeCms低代码开发平台了解及认知以及遇到的问题
1.jeecms低代码开发平台自带标签,使用的标签延续freemarker标签或基于freemarker标签自定的标签(类似自jsp自定义标签) (1)什么是freemarker标签: FreeMar ...