[缘起] 前端 E2E 测试的困境
与其它自动化测试不同,前端的 E2E 测试一直是个老大难问题,难点主要在于 如何描述测试。
自动化测试的核心是检查特定输入能不能得到符合预期的结果。对于单元测试和 API 测试来说,“特定输入”就是函数或者接口的参数,结果也是当前语言的数据类型或者通用的比如 JSON,二者一方面好描述,另一方面好验证。写起来就没什么难度。
比如
sum(a, b) { return a + b; }
要验证输入 1 和 2,返回 3,则可以写成:
const assert = require('assert'); describe('sum', function() { it('should equal', function() { assert.equal(sum(1, 2), 3); }); });
这里输入输出都很容易描述,所以自动化测试就没什么难度。
但是 UI 的 E2E 测试并非如此。UI 是做给用户看的,所以,一个 UI 的 E2E 测试应该写成这种形式(这里拿一个类似于活动行的应用来举例子):
- 打开应用首页
- 显示活动列表
- 点击列表中的任一项
- 进入活动详情页
- 点击报名按钮
- 登记个人信息
- 点击付费按钮
- 完成付费
- 看到报名成功的信息
这个过程当中用户的操作,很难和程序当中的抽象产物,比如按钮、列表等产生关联。操作的结果,“进入下一页”,也很难进行进一步的校验。
所以在之前的生产实践中,大家喜欢用选择器来进行 E2E 测试,代表产品有 Cypress 和 Nightwatch。我觉得,这里一方面有 jQuery 带来的使用习惯延续和思维定势;另一方面,借助 XPath,找到特定元件,进行交互操作和校验元素几乎是大家唯一的选择。
使用 CSS 选择器的方案并不完美,比如:
- 选择器本身,和 UI 视图可能并没有强关联,写出来的测试可读性不强,一段时间之后回头去看,很可能会看不懂。
- HTML 的 DOM 结构并不稳固,随着功能增减版本迭代经常发生变化,这个时候我们就要跟着修改测试用例。
- DOM 结构不能反应视图的真实状态,很可能会出现虽然测试通过,但实际上在用户眼里仍然是错误的表现。
那么,说了这么多不容易、其它方案的不完美,我的解决方案又是怎么样的呢?
这里请容许我卖一下关子,下次再介绍由我厂 OpenResty Inc. 打造的前端自动化工具 Navlang。
大家好,我是 Meathill,目前在 OpenResty Inc. 负责前端开发工作。今年我会利用业余时间,介绍我厂在前端方面的工作,包括各种垂直领域,比如自动化、基于 DevTool Protocol 开发、WebExtension 开发、Vue、CodeMirror、组件化等等,内容包括进展、经验、心得、踩坑、产品等。
欢迎大家关注本专栏,也欢迎大家光临我的博客:山维空间。如果你有任何疑问问题都可以在 SF 和我的博客上向我发问,我一定尽量答复。