安装 vue-cli

vue-test-utils 是 Vue 官方的测试库,并将在本指南中贯穿始终。它在浏览器和 Node.js 环境中皆可运行,并能配合任何 test runner 使用。在本指南中,我们将在 Node.js 环境运行测试。

vue-cli 是起步的最简单方式。它将建立一个项目,也会配置 Jest,一个流行的测试框架。其安装方法是:

  1. yarn global add @vue/cli

或通过 npm:

  1. npm install -g @vue/cli

通过运行 vue create [project-name] 来创建一个新项目。选择 “Manually select features” 和 “Unit Testing”,以及 “Jest” 作为 test runner。

一旦安装完成,cd 进入项目目录中并运行 yarn test:unit。如果一切顺利,你将看到:

  1. PASS tests/unit/HelloWorld.spec.js
  2. HelloWorld.vue
  3. renders props.msg when passed (26ms)
  4. Test Suites: 1 passed, 1 total
  5. Tests: 1 passed, 1 total
  6. Snapshots: 0 total
  7. Time: 2.074s

恭喜,你已经运行了你的第一个通过的测试!

编写你的首个测试

我们已经运行了项目中既有的一个测试。让我们撸起袖子,编写我们自己的组件,以及一个测试吧。以 TDD 方式的传统来说,你先编写一个失败的测试,然后实现代码以使该测试通过。但现在,我们将先编写组件。

我们不再需要 src/components/HelloWorld.vuetests/unit/HelloWorld.spec.js 了,所以你可以删掉它们。

创建 Greeting 组件

src/components 中创建一个 Greeting.vue 文件。在 Greeting.vue 中添加如下代码:

  1. <template>
  2. <div>
  3. {{ greeting }}
  4. </div>
  5. </template>
  6. <script>
  7. export default {
  8. name: "Greeting",
  9. data() {
  10. return {
  11. greeting: "Vue and TDD"
  12. }
  13. }
  14. }
  15. </script>

编写测试

Greeting 只有唯一的职责 — 渲染 greeting 的值。其测试策略为:

  1. mount 渲染组件
  2. 断言组件的文本中包含 “Vue and TDD”

tests/unit 中创建一个 Greeting.spec.js。在其内容中,引入 Greeting.vue,以及 mount 方法,并添加测试的概要:

  1. import { mount } from '@vue/test-utils'
  2. import Greeting from '@/components/Greeting.vue'
  3. describe('Greeting.vue', () => {
  4. it('renders a greeting', () => {
  5. })
  6. })

用于 TDD 的由很多不同的语法,我们将使用通常所见的 describeit 语法,由 Jest 提供。describe 一般概述了测试会包含什么,在本例中写的是 Greeting.vueit 表示测试应该完成的主题中一段单独的职责。随着我们为组件添加更多特性,在测试中就会添加更多 it 块。

现在我们应该用 mount 渲染组件。标准做法是将组件引用赋值给一个叫做 wrapper 的变量。我们也将输出结果打印出来,以确保一切正常:

  1. const wrapper = mount(Greeting)
  2. console.log(wrapper.html())

运行测试

通过在终端中输入 yarn test:unit 来运行测试。tests 目录中任何以 .spec.js 结尾的文件都会被自动执行。如果不出所料,你应该看到:

  1. PASS tests/unit/Greeting.spec.js
  2. Greeting.vue
  3. renders a greeting (27ms)
  4. console.log tests/unit/Greeting.spec.js:7
  5. <div>
  6. Vue and TDD
  7. </div>

我们可以看到置标语言是正确的,测试也通过了。测试通过是因为并没有失败 — 这个测试是不可能失败的,所以也没什么用。即便我们更改了 Greeting.vue 并从模板中删除了 greeting,测试都照样能通过。让我们改变这些。

做出断言

我们需要做出断言以确保组件行事正确。我们可以使用 Jest 的 expect API 做到这点。它看起来会是 expect(result).to [matcher] (actual) 这样。

matchers 是用来比较值和对象的一些方法。例如:

  1. expect(1).toBe(1)

一个关于 matchers 的完整列表可以在 Jest 文档设置 TDD - 图1 中找到。vue-test-utils 中并不包含任何的 matchers — Jest 提供的那些就足够了。我们要比较 Greeting 中的文本。可以这样写:

  1. expect(wrapper.html().includes("Vue and TDD")).toBe(true)

vue-test-utils 有一个更好的方式来比较置标 — wrapper.text。让我们完成测试:

  1. import { mount } from '@vue/test-utils'
  2. import Greeting from '@/components/Greeting.vue'
  3. describe('Greeting.vue', () => {
  4. it('renders a greeting', () => {
  5. const wrapper = mount(Greeting)
  6. expect(wrapper.text()).toMatch("Vue and TDD")
  7. })
  8. })

我们不再需要 console.log 了,所以你可以删除它了。通过 yarn unit:test 运行测试,如果一切正常将得到:

  1. PASS tests/unit/Greeting.spec.js
  2. Greeting.vue
  3. renders a greeting (15ms)
  4. Test Suites: 1 passed, 1 total
  5. Tests: 1 passed, 1 total
  6. Snapshots: 0 total
  7. Time: 1.477s, estimated 2s

看起来不错,但你应该总是看见一个测试失败,再让它通过,以确保它是真实可行的。在传统的 TDD 中,你应该在编写真正的实现之前先写测试,看着它失败,然后使用报错来引导你的编码。让我们来更新 Greeting.vue,确保该测试是真正可行的:

  1. <template>
  2. <div>
  3. {{ greeting }}
  4. </div>
  5. </template>
  6. <script>
  7. export default {
  8. name: "Greeting",
  9. data() {
  10. return {
  11. greeting: "Vue without TDD"
  12. }
  13. }
  14. }
  15. </script>

现在通过 yarn test:unit 来运行测试:

  1. FAIL tests/unit/Greeting.spec.js
  2. Greeting.vue
  3. renders a greeting (24ms)
  4. Greeting.vue renders a greeting
  5. expect(received).toMatch(expected)
  6. Expected value to match:
  7. "Vue and TDD"
  8. Received:
  9. "Vue without TDD"
  10. 6 | const wrapper = mount(Greeting)
  11. 7 |
  12. > 8 | expect(wrapper.text()).toMatch("Vue and TDD")
  13. | ^
  14. 9 | })
  15. 10 | })
  16. 11 |
  17. at Object.<anonymous> (tests/unit/Greeting.spec.js:8:28)

Jest 给了我们一个良好的反馈。我们可以看到期望的和实际的结果,也能看到期望是在哪一行失败的。测试如期失败了。回到 Greeting.vue 做出修改并确保再次的测试能够通过。

下面我们将看到 vue-test-utils 提供的两个渲染组件的方法: mountshallowMount