本文作者:伏晓,声网 Agora Web 引擎研发工程师。本文先简略介绍了 Cypress 测试平台,之后介绍基于模型的测试(Model-Based Testing)办法,并应用其对风行的 TodoMVC 利用进行建模和测试。最初指出这一测试 Demo 的可改良之处,同时瞻望了基于模型测试的将来倒退。
Cypress 介绍
Cypress 是为古代 Web App 打造的下一代前端测试工具。应用古代 JavaScript 框架构建 Web 应用程序的开发人员或 QA 工程师都能够采纳 Cypress 疾速编写和运行 E2E(端到端)测试、集成测试和单元测试。
Cypress 的 Time travel 性能是它的最大亮点,反对回退至任意工夫的 Snapshot,像是在回放电影一样,将测试运行过程中的每个细节重现进去。能够十分疾速的定位问题,极大的进步了调试自动化测试的体验。让它不同凡响的是它的运行机制:大多数测试工具(如 Selenium)通过在浏览器内部运行并在网络上执行近程命令来运行,Cypress 恰恰相反——Cypress 在与你的应用程序雷同的生命周期里执行。其余方面劣势能够在 https://docs.cypress.io/zh-cn… 看到。
在它的运行界面中能够看到每一步的操作,只需点击你想重现的步骤即可看到该步的截屏。如下图所示,点击“找到蕴含 type 的元素”这一行代码,右侧就会呈现出此时的场景,并高亮出这个元素。
具体的介绍能够到 Cypress.io 官网查看。也能够间接下载 Cypress Real World App 进行实在利用场景的测试体验。在这一展现场景中,运行 100 个测试(包含约 30 个 API 测试和 70 个端到端测试)须要 5 分 30 秒,这一速度曾经比很多手工冒烟测试还要快。而他是齐全主动并可调式的。
须要留神的是必须期待 Node.js 服务器和 React 开发服务器启动结束后能力运行 Cypress 进行测试。
基于模型的测试
基于模型的测试(Model-based Testing)属于软件测试畛域的一种测试方法。依照此办法,测试用例能够齐全或局部的利用模型主动产生。MBT 则容许软件开发人员和测试人员,只关注建设零碎的正确性以及模型的规范性,再通过专门的 MBT 工具依据不同的测试用例设计策略从零碎模型生成牢靠的测试用例。
测试 Case 是由模型生成,而不是由源代码生成。因而,基于模型的测试又经常被当作黑盒测试的一种模式。对于简单的软件系统中,如何利用基于模型的测试还在摸索中,在测试学术界曾经有一些对于主动生成测试模型的论文发表。
长处
- 测试用例的保护更轻松:保护好模型,无需关注测试用例的细节
- 软件缺陷发现的更早:在构建被测系统模型的过程中,须要对被测系统有比拟全面的了解,那么在晚期建模过程中就能够发现被测系统中的一些问题,不须要等到执行大量用例时才发现;
- 测试自动化的程度更高:建模后,MBT 能够主动生成测试用例,不须要人工编写测试文档;
- 测试覆盖率变得更高,使得彻底的测试(即:穷尽测试)成为可能:传统测试设计的过程中依赖人工,MBT 生成测试门路时会防止人工设计测试用例时的思维局限性,生成更丰盛的测试门路用例,然而是否须要执行“彻底”的测试由漏测对业务的影响决定。MBT 只是从技术上提供了穷尽测试可能性。
- 基于模型间接保护测试用例的形式更高效:传统保护时须要依赖人工,须要消耗大量的人力和工夫老本,从新测试设计。应用 MBT 只须要保护好测试模型即可,生成测试用例的工作能够由 MBT 工具主动实现;
毛病
- 学习老本较高:要求开发人员、测试人员都精通建模,和工具的选型;
- 应用 MBT 的初期投资较大:已有的 MBT 工具不肯定适宜本人产品,定制的话须要思考扩展性,和解决简单逻辑,也就是要花费大量工夫和精力;
- 用例爆炸
应用 @xstate/test 对 TodoMVC 进行基于模型的测试
Todo MVC 是前端风行的一个用于展现古代 JavaScript 框架和状态治理性能的 Web App。它的 Spec 能够在 https://github.com/tastejs/todomvc/blob/master/app-spec.md 找到。@xstate/test
是由微软的 David Khourshid 编写的一个基于模型的测试生成工具,它是基于 Statecharts 这一无限状态机模型衍生出的工具。但它不仅能用于测试应用 xstate 编写的软件,对所有能被模型化的 Web App 根本都能通过这一工具进行基模测试。
应用 @xstate/test
对某一零碎进行基于模型的测试有如下几个步骤:
- 创立对该利用形容的 Statecharts 形象模型
- 通过可视化工具等办法确保模型的一致性
- 在模型的状态中增加确保零碎处在该状态的断言
- 提供利用状态转换的事件与实在操作
- 应用测试框架运行主动生成的测试
上面我尝试应用 xstate 软件对有一个 Todo 我的项目的状况进行简略建模。该 TodoMVC 代码 fork 自 Cypress 的官网示例:GitHub – cypress-io/cypress-example-todomvc: The official TodoMVC tests written in Cypress.。
对 Todo Item 进行建模
其中 Unknown 是一个两头过渡状态,它能够确保该 Todo 状态机正确保留了外部的状态并进行转换。能够参考:
- https://xstate.js.org/docs/guides/history.html
- https://xstate.js.org/docs/guides/transitions.html#transient-transitions
该模型的代码能够在这个 GitHub Gist 上看到:todo.machine.js · GitHub
TodoMVC 的 Todo Item 的 Statecharts 模型——通过 xstate 可视化工具生成
增加状态的断言
在要测试的状态节点(Unknown 的过渡状态除外)中增加确保 App 处在这一状态的断言:
Editing: {
meta: {test: () => {cy.get('.todo-list li').should('have.class', 'editing');
cy.get('.main').should('be.visible');
cy.get('.footer').should('be.visible');
},
},
}
这里用到了 Cypress 的选择器和断言工具,确保在编辑状态时的 UI 状态是正确的。这样顺次增加实现所有状态的断言。
增加状态转换事件
在状态模型中定义的形象状态转换事件并不能使测试 App 的实在状态产生转换,所以要在测试模型中注入能使该事件正确产生的 UI 办法调用。
- 应用 Cypress 提供的函数产生转换事件
生成用例和运行测试
有了下面这些筹备,当初 @xstate/test
就能够主动生成并运行测试:
const testPlans = testModel.getSimplePathPlans();
testPlans.forEach((plan) => {plan.paths.forEach((path) => {it(path.description, () => {
return cy
.get('.new-todo')
.type('Hello World!{enter}')
.then(() => {return path.test(cy);
});
});
});
});
同时你也能够调用 Test Model 上的 testCoverage
办法取得不同状态的覆盖率报告:
it('coverage', () => {
testModel.testCoverage({filter: (stateNode) => !stateNode.id.startsWith('Todo.Unknown'),
});
});
应用 @xstate/test + cypress 进行测试的界面
问题与瞻望
因为对该利用定义的状态非常复杂,所以只能执行最短门路用例生成,不能执行简略门路用例生成,否则会因为状态太多生成过多测试用例,导致利用卡死。
简略门路的图示
最短门路的图示
但这也只是 Todo MVC 最简略(只有一个 Todo 我的项目)的状态机,如果 Todo 数量减少,状态数量将呈指数增长。所以如果要将该测试方法利用到理论,还须要更高阶层的形象或者更加自动化的办法来生成测试对象的状态模型。
举荐资源
- xstate 作者对于 Model-Based Testing 的演讲:Write Fewer Tests! From Automation to Autogeneration – David Khourshid – React Rally 2019
- 应用 Learning-Based Testing 办法主动生成 Todo MVC 的状态模型的文章:Model-Based Testing Without Models: The TodoMVC Case Study