学习了一段时间 Vue 组件单元测试相关知识,感觉比起用什么测试框架、怎么写测试更重要的是搞明白组件测试应该测什么,这里就总结一下自己的一些思考。
组件测试不应该测什么
-
单纯测试组件模板中的 HTML
比如,测试组件模板中有几个
div
、input
、button
,以及元素的class
、id
属性等与业务逻辑无关的纯 UI 测试。这里并非说我们不需要关注组件的 UI,而是出于以下几个考量: -
测试组件的内部方法
如果一些方法只是在组件内部调用其他方法而没有任何暴露给外部的行为(比如更改了组件的 UI、请求外部 API 等),那这些方法是不需要测试的。我们希望一个组件就像一个黑盒一样,我们不关心其内部的处理逻辑而只关注其外部呈现。
You should test your component's public interface and side effects.
组件测试应该测什么
这里以 Vue 组件来总结一下组件测试需要测什么。
-
测试组件是一个 Vue 实例
test("is a Vue instance", () => { const wrapper = shallowMount(MyComponent); expect(wrapper.isVueInstance()).toBeTruthy(); });
这个测试应该置于该组件所有其他单元测试之前,以保证该组件能够正常挂载
-
测试组件实例的数据
由于组件的渲染是依赖
props
、data
以及计算属性computed
的,因此需要针对这些数据进行测试,如- 给定
props
下,初始的data
是否正确 - 给定
props
和data
后,计算属性的值是否正确 - 在父组件中测试
props
是否正确传递给子组件
- 给定
-
测试组件实例的渲染结果
同样因为组件的渲染依赖
props
、data
、computed
这些数据,因此需要 mock 这些数据来测试不同数据作用下的渲染结果是否符合预期,如测试本文内容是否与数据一致
-
测试条件渲染的结果
元素或子组件的存在性是否随数据的变化而变化
-
测试循环渲染的结果
元素或子组件的数量是否与数据一致
-
测试组件实例的事件
用户与 UI 的交互是通过事件完成的,因此需要针对事件进行测试,如
-
触发
click
、input
等事件后组件上的自定义事件是否被触发比如 Todo List App 的
add-todo
等一系列自定义事件能否被触发 -
触发事件后对应的处理方法是否被调用,以及是否使用预期的参数调用
需要注意的是,这里主要测试的是一些对外的方法,比如调用 API 等
触发事件后
data
是否按预期更新-
触发事件后组件是否按预期渲染
如果已经有测试用例测试过事件能更新
data
、且组件能根据data
渲染,则无需再测试组件能根据事件渲染
-
使用 Vuex 管理数据的组件应该怎么测
使用 Vuex 管理数据流后,我们需要额外针对getters
、mutations
、actions
等进行测试,以保证组件的数据和行为是符合我们预期的。针对 Vuex 的测试有两个要点:
由于
getters
、mutations
、actions
实际上都是普通的函数,因此我们可以通过测试这些函数在给定输入下是否有预期输出来保证它们的正确性-
结合Vuex 的作用原理,我们可以按照 Vuex 中数据的流向设计测试用例
一个由 Vuex 管理数据流的 App 大致是按照如下的方式工作的:
- 用户与 UI 交互触发事件
- 事件的监听函数 dispatch 相应的
action
-
action
提交包含类型和数据的mutation
-
mutation
负责处理具体的业务逻辑,更新 App 的state
-
getters
进而会根据state
重新计算 - 组件监听到
state
的变化而重新渲染
在理解上述要点的情况下,我们可以总结出针对 Vuex 的一些测试方法:
- 模拟事件的触发,测试是否 dispatch 相应的
action
- mock 掉
commit
方法,测试action
函数是否能使用正确的参数 commitmutation
- 测试给定参数下,
mutations
能否正确修改state
- 测试给定
state
时,getters
的计算结果是否正确 - 给定
state
和getters
下,测试组件接收到的props
是否正确 - 给定
props
下组件能否正确渲染
怎么使用快照测试
上述总结的单元测试方法主要测试的是组件的行为是否与预期相符,为了更全面的测试组件 UI,我们可以使用快照测试。
快照测试带来的好处是可以清晰的对比出 UI 的变化,让开发人员确认是必要的改变还是引入的 bug,避免了为测试 UI 导致单元测试过于陷入细节和脆弱。
需要注意的是,快照测试是不能够替代单元测试的,因为它只是对 UI 历史版本的记录,无法用于描述所期望的 App 的行为,因而不能够像传统的单元测试一样做为所开发的 App 的“使用文档”,它应该和单元测试一起互为补充。