vitest

2023/11/29 工具链测试vue3

这是关于使用 vitest (opens new window) 进行vue3 组件单元测试 (opens new window)的文章。另外还用到了 @vue/test-utils (opens new window) 依赖包。总体和之前常用的 jest (opens new window) 的使用方法类似,可以从 vitest 依赖包导出和 jest 一样的方法。

vue3 官网推荐首先的是 vue-testing-library (opens new window) ,但笔者认为上手难度要比 @vue/test-utils 要高一些的。不好找到代码示例,然后文档看的一头雾水。对于笔者来说还是选择 @vue/test-utils 包比较好上手。接下来看看如何使用 vitest 和 @vue/test-utils 来进行单元测试吧。

# 基础用法

首先安装 vitest 和 @vue/test-utils 依赖包:

npm install -D vitest
npm install -D @vue/test-utils
npm install -D @vitest/coverage-c8
1
2
3

在 package.json 写上:

{
	"scripts": {
	  "test": "vitest",
    "coverage": "vitest run --coverage"
	}
}
1
2
3
4
5
6

以 element-plus 的 button 组件的测试源码 (opens new window)为例:

import { nextTick, ref } from 'vue'
import { mount } from '@vue/test-utils'
import { describe, expect, it, test } from 'vitest'
import { Loading, Search } from '@element-plus/icons-vue'

import Button from '../src/button.vue'
import type { ComponentSize } from '@element-plus/constants'

const AXIOM = 'Rem is the best girl'

describe('Button.vue', () => {
  it('create', () => {
    const wrapper = mount(() => <Button type="primary" />)

    expect(wrapper.classes()).toContain('el-button--primary')
  })

  it('size', () => {
    const wrapper = mount(() => <Button size="large" />)

    expect(wrapper.classes()).toContain('el-button--large')
  })

  it('text', async () => {
    const bg = ref(false)

    const wrapper = mount(() => <Button text bg={bg.value} />)

    expect(wrapper.classes()).toContain('is-text')

    bg.value = true

    await nextTick()

    expect(wrapper.classes()).toContain('is-has-bg')
  })

  test('render text', () => {
    const wrapper = mount(() => (
      <Button
        v-slots={{
          default: () => AXIOM,
        }}
      />
    ))

    expect(wrapper.text()).toEqual(AXIOM)
  })

  test('handle click', async () => {
    const wrapper = mount(() => (
      <Button
        v-slots={{
          default: () => AXIOM,
        }}
      />
    ))

    await wrapper.trigger('click')
    expect(wrapper.emitted()).toBeDefined()
  })

  test('handle click inside', async () => {
    const wrapper = mount(() => (
      <Button
        v-slots={{
          default: () => <span class="inner-slot"></span>,
        }}
      />
    ))

    wrapper.find('.inner-slot').trigger('click')
    expect(wrapper.emitted()).toBeDefined()
  })

  it('disabled', async () => {
    const wrapper = mount(() => <Button disabled />)

    expect(wrapper.classes()).toContain('is-disabled')
    await wrapper.trigger('click')
    expect(wrapper.emitted('click')).toBeUndefined()
  })

  it('loading slot', () => {
    const wrapper = mount({
      setup: () => () =>
        (
          <Button
            v-slots={{ loading: () => <span class="custom-loading">111</span> }}
            loading={true}
          >
            Loading
          </Button>
        ),
    })

    expect(wrapper.find('.custom-loading').exists()).toBeTruthy()
  })
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99

it 和 test (opens new window) 其实没什么区别,it 是 test 的区别。同一个源码文件会有 it 和 test 的原因,很大可能是因为不是一个人写的,而且可能是复制粘贴的。

test 是一个测试用例,describe 用来归类。看完上面的示例,基本就知道如何进行 vue3 组件的单元测试了,不懂的话就多看几个组件的测试代码 😑😑😑

更新时间: 2023/11/29 15:42:16