安装
yarn add -D vitest || npm install -D vitest
配置命令
在项目中,需要配置后才可以使用
// ...
export default defineConfig({
test: {
//...
include: ['test/**/*.test.ts'], //匹配包含文件
// exclude:[], // 排除文件
environment: 'jsdom', //浏览器环境
},
})
{
"scripts": {
"test": "vitest",
}
}
- 可选 @vitest/coverage-c8 c8代码覆盖率测试
yarn add @vitest/coverage-c8 -D || npm install @vitest/coverage-c8 -D
{
"scripts": {
// ...
"coverage": "vitest run --coverage",
}
}
- 可选 jsdom 测试浏览器环境
yarn add jsdom -D || npm install jsdom -D
export default defineConfig({
//...
test: {
environment: 'jsdom'
}
})
- 可选 @vitest/ui
可以添加 @vitest/ui vitest 的UI扩展库,可以直接在浏览器查看
yarn add @vitest/ui -D || npm install @vitest/ui -D
{
"scripts": {
"vitestui": "启动vitest的UI界面",
"vitestui": "vitest --ui"
}
}
- 可选 ndb debugger
yarn add ndb gloable || npm install ndb -g
之后在想要的地方写 debugger ,在使用test进行测试就行
- 可选 在代码里写测试
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
environment: 'node',
includeSource: ['src/*.{js,ts}']
}
})
- 可选 使用@vue/test-utils对vue组件测试
yarn add –dev @vue/test-utils || npm install –save-dev @vue/test-utils
简单示例
import { mount } from '@vue/test-utils'
import TodoApp from './TodoApp.vue'
test('renders a todo', () => {
const wrapper = mount(TodoApp) //包裹
const todo = wrapper.get('[data-test="todo"]') //查找标签元素
expect(todo.text()).toBe('Learn Vue.js 3') //断言文本
})
单元测试示例
在根目录添加 __tests__
文件夹,添加测试文件
import { expect, test } from 'vitest'
import { testName } from '../src/index'
test('vitest-test', () => {
expect(testName('jack')).toBe('jack')
})
export function testName (name) {
return name
}
简单介绍
test 别名it
test 定义了一组关于测试期望的方法。它接收测试名称(类似备注名称)和一个含有测试期望的函数,同时,可以提供一个超时时限(以毫秒为单位)用于指定等待多长时间后终止测试,默认为 5 秒
// 超时阈值(以毫秒为单位)作为第三个参数传递给测试。默认值为 5 秒
import { assert,test } from 'vitest'
// 示例
test('name', async () => { /* ... */ }, 1000)
// test.skip :跳过测试,没有错误
test.skip("skipped test", () => {
assert.equal(Math.sqrt(4), 3);
});
// test.skipIf :需要根据条件,跳过测试
const isDev = process.env.NODE_ENV === "development";
test.skipIf(isDev)("prod only test", () => {
// 只要是开发环境就跳过
});
// test.runIf :需要根据条件,运行测试
test.runIf(isDev)("dev only test", () => {
// 只在开发环境下进行测试
});
// test.only :只允许特点条件下运行
test.only("test", () => {
// 仅运行此测试(以及仅标记有的其他测试)
assert.equal(Math.sqrt(4), 2);
});
// test.concurrent :并行运行测试
test.concurrent("concurrent test 1", async () => { });
test.concurrent("concurrent test 2", async () => { });
// test.skip、test.only 和 test.todo 适用于并发测试
test.skip.concurrent(/* ... */); // or test.concurrent.skip(/* ... */)
test.only.concurrent(/* ... */); // or test.concurrent.only(/* ... */)
test.todo.concurrent(/* ... */); // or test.concurrent.todo(/* ... */)
// test.todo 存根测试
// 测试报告中将显示一个条目,不知道有什么用
test.todo("unimplemented test");
// test.fails
//使用 test.fails 来指示测试断言将显式失败(不知道有什么屌用,没看到效果)
const myAsyncFunc = () => new Promise((resolve) => resolve(1));
test.fails("failtest", async () => {
await expect(myAsyncFunc()).rejects.toBe(1);
});
// test.each 相同测试
// 当你需要使用不同的变量运行相同的测试时,请使用 test.each。 你可以按照测试参数的顺序,在测试名称插入符合printf 格式的参数
// %s:字符串; %d:数值; %i:整数; %f:小数; %j:json 格式; %o:对象; %#:对应的测试参数下标; %%:单个百分比符号 ('%')
test.each([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])("name", (a, b, expected) => {
expect(a + b).toBe(expected);
});
expect 断言
expect 用来创建断言。在当前上下文中,可以使用 assertions 方法来断言一个语句。 Vitest 默认提供 chai 进行断言,同时基于 chai 实现兼容 Jest 的断言语句
import { expect } from "vitest";
const input = Math.sqrt(4);
expect(input).toBe(2); //断言input的值是2
// not 否定断言
expect(input).not.toBe(2); //断言input的值不是2
// toBe 相同断言 (禁止使用浮点型)
const stock = {type:"apples", count: 13}
expect(stock.count).toBe(13); //断言stock.count等于13
// toBeCloseTo 相同断言 (浮点型)
expect(0.2 + 0.1).toBeCloseTo(0.3, 5); //toBeCloseTo(结果,小数点后位数)
// toBeDefined 断言有返回
expect( () => 3 ).toBeDefined(); //断言值不是是undefined,可以用来判断函数有返回值
// toBeUndefined 断言无返回
const an=()=>undefined
expect( an() ).toBeUndefined(); //断言值是undefined,可以用来判断函数没有返回值
// toBeTruthy 断言为真
expect(0.2 + 0.1).toBeTruthy(); //将结果转为布尔值,结果为true
// toBeFalsy 断言为假
expect(5-5).toBeFalsy()
// toBeNull 断言为null
expect(null).toBeNull()
// toBeNaN 断言为NaN
expect(NaN).toBeNull()
// toBeTypeOf 断言类型(bigint, boolean, function, number, object, string, symbol, undefined)
expect('actual').toBeTypeOf("string"); //断言类型为string
// toBeInstanceOf 断言父类
const stocks = new Stocks();
test("stocks are instance of Stocks", () => {
expect(stocks).toBeInstanceOf(Stocks); //断言你的父类是它(断言他是你爸)
});
// toBeGreaterThan 断言大小
expect(5).toBeGreaterThan(1); //断言 5 大于 1
// toBeGreaterThanOrEqual 断言大小
expect(5).toBeGreaterThanOrEqual(1); //断言 5 大于等于 1
// toBeLessThan 断言大小
expect(1).toBeLessThan(5); //断言 1 小于 5
// toBeLessThanOrEqual 断言大小
expect(1).toBeLessThanOrEqual(5); //断言 1 小于等于 5
toEqual
toStrictEqual
toContain
toContainEqual
toHaveLength
toHaveProperty
toMatch
toMatchObject
toThrowError
toMatchSnapshot
toMatchInlineSnapshot
toThrowErrorMatchingSnapshot
toThrowErrorMatchingInlineSnapshot
toHaveBeenCalled
toHaveBeenCalledTimes
toHaveBeenCalledWith
toHaveBeenLastCalledWith
toHaveBeenNthCalledWith
toHaveReturned
toHaveReturnedTimes
toHaveReturnedWith
toHaveLastReturnedWith
toHaveNthReturnedWith
toSatisfy
resolves
rejects
// expect.assertions 断言异步调用几次
async function doAsync(...cbs) {
await Promise.all(cbs.map((cb, index) => cb({ index })));
}
test("all assertions are called", async () => {
expect.assertions(2); // 本次异步调用了两次
function callback1(data) {
expect(data).toBeTruthy(); //断言为真,函数有返回
}
function callback2(data) {
expect(data).toBeTruthy(); //断言为真,函数有返回
}
await doAsync(callback1, callback2);
});
// expect.hasAssertions 断言至少调用一次
function select(id) {
return db.select({ id }).then((data) => {
return Promise.all(cbs.map((cb) => cb(data)));
});
}
test("callback was called", async () => {
expect.hasAssertions(); // 本次调用了
onSelect((data) => {
expect(data).toBeTruthy();
});
await select(3);
});
expect.anything
expect.any
expect.arrayContaining
expect.objectContaining
expect.stringContaining
expect.stringMatching
expect.addSnapshotSerializer
expect.extend
bench 基准
bench
定义了一个基准。 在 Vitest 术语中,基准是定义一系列操作的函数。 Vitest 多次运行此函数以显示不同的性能结果
import { bench } from "vitest";
bench( // 报错: Error: `bench()` is only available in benchmark mode.
"normal sorting",
() => {
const x = [1, 5, 4, 2, 3];
x.sort((a, b) => {
return a - b;
});
},
{ time: 1000 }
);
bench.skip
bench.only
bench.todo
describe 套件
当你在文件的顶层使用 test 或 bench 时,它们会被收集为它的隐式套件的一部分。 使用 describe 你可以在当前上下文中定义一个新套件,作为一组相关的测试或基准以及其他嵌套套件
import { test,describe } from 'vitest'
import { testName } from '../src/index'
const person = {
isActive: true,
age: 32,
};
describe("person", () => { //类似一个嵌套结构,仅用于展示效果
test("person is defined", () => {
expect(person).toBeDefin ed();
});
})
// describe.skip 跳过
describe.skip("skipped suite", () => {
test("sqrt", () => {
// 跳过测试套件,不会有错误
assert.equal(Math.sqrt(4), 3);
});
});
// describe.only 只运行里面的,其他的不运行
describe.only("skipped suite", () => { //执行
test("sqrt", () => {
assert.equal(Math.sqrt(4), 3);
});
});
test("sqrt", () => { //不执行
assert.equal(Math.sqrt(4), 3);
});
describe.concurrent
describe.shuffle
describe.todo
describe.each
Vi 工具函数
// vi.advanceTimersByTime 定时停止
let i = 0;
setInterval(() => console.log(++i), 50);
vi.advanceTimersByTime(150); // 150 毫秒后停止执行
vi.advanceTimersToNextTimer
vi.clearAllMocks
vi.clearAllTimers
vi.dynamicImportSettled
vi.fn
vi.getMockedSystemTime
vi.getRealSystemTime
vi.mock
vi.mocked
vi.importActual
vi.importMock
vi.resetAllMocks
vi.resetConfig
vi.resetModules
vi.restoreAllMocks
vi.restoreCurrentDate
vi.runAllTicks
vi.runAllTimers
vi.runOnlyPendingTimers
vi.setSystemTime
vi.setConfig
vi.spyOn
vi.stubGlobal
vi.unmock
vi.useFakeTimers
vi.useRealTimers
MockInstance Methods
getMockName
mockClear
mockName
mockImplementation
mockImplementationOnce
mockRejectedValue
mockRejectedValueOnce
mockReset
mockRestore
mockResolvedValue
mockResolvedValueOnce
mockReturnThis
mockReturnValue
mockReturnValueOnce
MockInstance Properties
mock.calls
mock.lastCall
mock.results
mock.instances
问题集合
执行vitestui 报错 Cannot read properties of undefined (reading ‘config’)
vitest 和 vitest/ui 的版本和 vite 不匹配
pnpm i vitest@latest @vitest/ui@latest -D