配置测试脚本
在很多情况下,测试脚本的编写并不是前端工程师的主要工作。在国内大多数的开发团队中,并不会去要求前端工程师去编写测试脚本。一来是增加了开发的工作量以及学习成本,二来是每个团队都会配备测试工程师者一角色来保证项目的质量。甚至有些时候,前端开发人员编写测试脚本反倒成了“吃力不讨好”的事情。不过,编写测试脚本仍然是非常有意义的,因为测试脚本可以保证代码的质量,提高代码的可维护性以及稳定性。
是否编写测试脚本,应根据项目需求、团队成员技术能力等因素综合考虑。如果明确项目不需要编写测试脚本,那么本章节的内容可以忽略。
认识前端测试脚本
常说的的前端测试脚本分为两类:单元测试和端到端测试。
单元测试(Unit Testing)是针对程序中最小可测试单元进行的测试工作,比如函数、模块、组件等。单元测试的目的是验证代码的正确性,确保代码按照预期工作。
端到端测试(End-to-End Testing,简称 E2E 测试)是一种从头到尾测试整个软件产品以确保应用程序流程按预期运行的技术。它模拟真实用户场景并验证被测系统及其组件的集成和数据完整性,主要从最终用户的体验进行测试。其核心目标是确保系统在实际使用环境中能够正常运行,提供高质量的服务。
从上面的描述不难看出,单元测试和端到端测试的目的都是验证代码的正确性,但它们的侧重点不同。单元测试侧重于验证代码的功能,而端到端测试侧重于验证业务流程的完整性。在实际的项目团队中,业务功能的验证往往是测试工程师来完成。他们有着更加完备的技能和专业的理论知识来完成这部分工作。而对于单元测试,由于测试工程师无法操作查验代码,因此无法进行。基于以上种种的考量,除了那些开发资源充裕、对代码质量要求极高的团队,大多数团队基本只要求开发人员进行单元测试脚本的编写。
测试脚本的作用
项目中编写测试脚本的作用主要有以下几点:
- 提高代码质量:可以提前发现代码中的问题,提高代码质量。
- 提高开发效率:可以减少调试时间,提高开发效率。
- 提高代码可维护性:可以确保代码在修改后仍然按照预期工作,提高代码的可维护性。
- 提高代码可读性:可以提供代码的示例用法,提高代码的可读性。
上述几点中,我认为提高代码可维护性以及提高代码可读性是编写测试脚本的核心目的。这两点在单元测试中尤为重要,因为单元测试的目的是验证代码的正确性,确保代码按照预期工作。如果代码在修改后仍然按照预期工作,那么代码的可维护性就得到了保证。如果代码的示例用法清晰明了,那么代码的可读性就得到了保证。
测试脚本环境的搭建
将测试脚本集成到项目中,需要搭建测试脚本的环境。测试脚本的环境搭建主要包括以下内容:
- 测试框架的安装
- 测试脚本的组织
- 执行命令的封装
本章节以单元测试为例,介绍如何搭建测试脚本的环境。
测试框架的安装
前端常用的单元测试框架有 Jest、Mocha、Jasmine、Vitest 等。其中 Vitest 是一个基于 Vite 的前端测试框架,它使用 Vite 的构建能力来构建测试环境,并使用 Vite 的插件系统来扩展测试功能。Vitest 支持使用 TypeScript 编写测试脚本,并支持使用 Jest、Mocha、Jasmine 等测试框架的语法。Vitest 依托于 Vite 优越性能和 Vue 生态的强相关性,逐渐发展为 Vue 项目的首选测试框架。因此,本章节以 Vitest 为例,介绍如何安装 Vitest。
Vitest 的安装非常简单,只需要在项目中安装 Vitest 即可。在项目中安装 Vitest 的命令如下:
yarn add vitest --dev
TIP
Vitest 需要 Vite >=v5.0.0 和 Node >=v18.0.0
配置 Vitest
Vitest 有两种配置方式。一种是将其合并到 Vite 配置文件中,即在vite.config.js
中编写。另一种是单独创建一个vitest.config.js
文件。
在vite.config.js
中编写 Vitest 配置的示例如下:
import { defineConfig } from 'vite'
export default defineConfig({
test: {
// ...
}
})
如果你想要单独的配置文件,或者你的项目不使用 Vite 作为构建工具。则可以在项目根目录创建一个vitest.config.js
文件,并在其中编写 Vitest 配置。示例如下:
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
// ...
}
})
WARNING
如果你决定为 Vite 和 Vitest 使用两个单独的配置文件,请确保在 Vitest 配置文件中定义相同的 Vite 选项,因为它将覆盖你的 Vite 文件,而不是扩展它。你还可以使用 vite 或 vitest/config 条目中的 mergeConfig 方法将 Vite 配置与 Vitest 配置合并。如下:
import { defineConfig } from 'vite'
import Vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [Vue()]
})
import { defineConfig, mergeConfig } from 'vitest/config'
import viteConfig from './vite.config.mjs'
export default mergeConfig(
viteConfig,
defineConfig({
test: {
// ...
}
})
)
测试脚本的组织
在项目中编写测试脚本时,需要将测试脚本组织起来,以便于管理和执行。测试脚本的组织主要包括以下内容:
- 测试脚本的命名规则
- 测试脚本的目录结构
测试脚本的命名规则
测试脚本的命名应该遵循一定的规范,以便于管理、执行和理解。常见的命名规范有:
describe
:用于描述一组相关测试用例,例如describe('add', () => {})
it
/test
:用于描述测试用例的具体内容,例如it('should return 2 when add(1, 1)', () => {})
TIP
it
和 test
是等价的,可以互换使用。
如下:
import { describe, expect, test } from 'vitest'
const person = {
isActive: true,
age: 32
}
// describe 是一个函数,用于描述一组person测试用例
describe('person', () => {
test('person is defined', () => {
expect(person).toBeDefined()
})
test('is active', () => {
expect(person.isActive).toBeTruthy()
})
test('age limit', () => {
expect(person.age).toBeLessThanOrEqual(32)
})
})
TIP
Vitest 更多语法,可以参考:Test API 索引 | Vitest
测试脚本的目录结构
常用的测试脚本的目录结构有两种方式:其一,在项目根目录下创建一个test
目录,用于存放所有的测试脚本;其二,在项目的每个模块下创建一个__test__
目录,用于存放该模块的测试脚本。两种方式各有优劣,可以根据项目需求和个人习惯选择使用。
方式一的目录结构示例如下:
project
├── src
│ ├── components
│ ├── utils
│ ├── ...
├── test
│ ├── components
│ ├── utils
│ ├── ...
├── package.json
├── ...
方式二的目录结构示例如下:
project
├── src
│ ├── components
│ │ ├── __test__
│ │ ├── ...
│ ├── utils
│ │ ├── __test__
│ │ ├── ...
├── package.json
├── ...
执行命令的封装
接下来,为了便于执行测试脚本,我们需要在 package.json
文件中添 Vitest 执行命令:
{
"scripts": {
"test": "vitest"
}
}
TIP
关于 Vitest 命令的更多用法,可以参考:命令行界面
单元测试脚本编写
在编写单元测试前,我们需要明确几个问题:1. 哪些代码需要进行单元测试?2. 一个测试对象需要写哪些测试用例?3. 怎么组织单元测试代码?4. 应该在什么时候写单元测试?
只有搞清楚这些问题,我们才能更好地编写单元测试。下面,我们一一解答这些问题。
哪些代码需要进行单元测试?
前端的代码很多,不过我们并不需要对全部的代码编写单元测试。从单元测试的定义中可知,单元测试是对程序中最小、最基础单元进行的测试。这些单元的特点就是独立且可复用。例如,函数、模块、组件等。以 Vue 项目为例,这些单元包括:
- utils/中的导出的
Class
、Function
; - 公共组件:组件的渲染以及交互逻辑;
一个测试对象需要写哪些测试用例?
一个测试对象需要写哪些测试用例,取决于该对象的业务逻辑。一般来说,一个测试对象需要写以下测试用例:
- 正常情况下的测试用例;
- 异常情况下的测试用例;
- 边界情况下的测试用例。
怎么组织单元测试代码?
在编写单元测试代码时,我们需要遵循一定的规范,以便于管理和执行。一般来说,我们需要遵循以下规范:
- 采用统一的目录结构;
- 一个测试对象对应一个测试文件;
- 测试用例的命名应该清晰、简洁、具有描述性;
- 测试用例应该独立、可复用、可维护;
应该在什么时候写单元测试?
关于何时编写单元测试,业界有两种观点:一种观点是TDD(Test-Driven Development,测试驱动开发),即先编写测试用例,然后再编写代码实现测试用例。这种方法确保每个新添加或修改的功能都有相应的测试来验证其正确性;另一种观点是在编写功能代码的同时编写测试用例,在编写功能代码的同时考虑如何测试这些功能。每当实现一个新的功能或修改现有功能时,都应该同时编写相应的单元测试。
此外,如果项目进度比较急迫,则优先保证项目进度,过后另行补充单元测试即可。
写在最后
在本章中,我们学习了如何配置测试脚本,包括如何安装和配置 Vitest,以及如何编写单元测试脚本。通过学习,我们了解了如何编写测试用例,如何组织测试脚本,以及如何执行测试脚本。
正如开篇所说,测试工程师的出现已经能够确保项目质量无忧。在前端项目中引入测试脚本,其核心价值在于提升代码的可维护性和可读性,确保每一次代码变更都能精准无误地达到预期效果。至于是否要在项目中引入测试脚本,则需综合考虑项目的实际需求、团队成员的技术背景及专长等多维度因素,做出既灵活又全面的决策。