??? 交流討論:歡迎加入我們一起學習!
?? 資源分享:耗時200+小時精選的「軟件測試」資料包
???教程推薦:火遍全網的《軟件測試》教程??
??歡迎點贊 ?? 收藏 ?留言 ?? 如有錯誤敬請指正!
簡介
Vitest 是一個面向 Vite 的極快的單元測試框架。它利用了 Vite 的優(yōu)勢,提供了一種全新的測試體驗。本文將介紹如何在項目中集成和使用 Vitest 進行單元測試。
安裝 Vitest
npm install -D vitest
配置 Vitest
在項目根目錄下創(chuàng)建 vitest.config.js 文件,用于配置 Vitest。
更多詳細配置 cn.vitest.dev/config/
test: {
? ? globals: true,
? ? environment: 'happy-dom',
? ? restoreMocks: true,
? ? include: ['**/*.{test,spec,type-test}.{js,mjs,cjs,ts,tsx,jsx}'],
? ? coverage: {
? ? ? exclude: ['tests/**', '.eslintrc.cjs'],
? ? ? reporter: ['cobertura', 'text', 'html', 'clover', 'json'],
? ? },
? ? setupFiles: `${path.resolve(__dirname, 'tests/setup.ts')}`,
? ? snapshotFormat: {
? ? ? printBasicPrototype: true,
? ? },
? ? alias: []
? },
配置 Vitest公共文件
在項目根目錄下創(chuàng)建setup-test.ts文件,用于統(tǒng)一處理定時器,原生事件,以及在vitest環(huán)境下無法模擬的事件
import { vi, describe, it, expect } from 'vitest';
import '@testing-library/jest-dom/vitest';
import MockAdapter from 'axios-mock-adapter';
import axios from 'axios';
import { configure } from '.';
export const mock = new MockAdapter(axios);
configure({
? renderMode: 'global',
? enableMultipleSelection: false,
});
beforeEach(() => {
? mock.reset();
? console.error = vi.fn();
? console.warn = vi.fn();
? vi.useFakeTimers();
? window.requestIdleCallback = vi.fn();
? document.execCommand = vi.fn();
? window.onresize = vi.fn();
? vi.setSystemTime(new Date(1680278400000));
});
afterEach(() => {
? mock.reset();
? vi.useRealTimers();
});
window.vi = vi;
window.describe = describe;
window.it = it;
window.expect = expect;
·全局暴露 vi describe it expect 方法,如果以后更換測試框架,單元測試內部代碼無需改動
·?全局暴露mock,并在beforeEach 與 afterEach 清空相關的mock接口
·?初始化單元測試環(huán)境內時間
單元測試分類
·?單元測試:主要是對項目里的最小 組件 或模塊進行測試,一般是在非瀏覽器環(huán)境下的測試
·?集成測試:一般是對單元測試下的多個最小單元組成的較大 組件 或模塊進行小型的組合測試,一般是在非瀏覽器環(huán)境下的測試。
·?端到端 測試 (E2E) : 從用戶的視角出發(fā),基于整個頁面或者應用,模擬用戶操作測試,一般是在瀏覽器環(huán)境下的測試
如何編寫 單元測試
在項目src目錄平級的位置,新建tests文件,tests文件夾下新建mocks文件夾
·?mocks下主要存放對應單元測試模擬數(shù)據的文件
·?tests下主要存放對應的單元測試文件
如何模擬接口請求
在項目中引入axios-mock-adapter第三方工具庫,在進行測試的test文件下新建Mock文件夾,然后新建 test-demo-mock.ts文件。
詳細配置 github.com/ctimmerm/ax…
import { mock } from '../../../src/setup-test';
export const TestDemoMock = {
? getUsersTitle: (status: number) => {
? ? mock.onGet('/users/title').reply(status, { title: '江霧' });
? },
};?
編寫測試用例
新建一個test-demo.tsx文件,編寫React組件
import axios from 'axios';
import { useEffect, useState } from 'react';
const TextDemo: React.FC = () => {
? const [title, setTitle] = useState('測試');
? const getTitleValue = async () => {
? ? const response = await axios.get('/users/title');
? ? const { status, data } = response;
? ? if (status === 200) {
? ? ? setTitle(data.title);
? ? } else {
? ? ? // error
? ? ? setTitle('接口異常');
? ? }
? };
? const changeBtn = () => {
? ? setTitle('江霧');
? };
? return (
? ? <div className="test-dome-content">
? ? ? <span className="title"> {title} </span>
? ? ? <button className="refresh-button" onClick={getTitleValue}>
? ? ? ? refresh
? ? ? </button>
? ? ? <button onClick={changeBtn} className="change-btn">
? ? ? ? change
? ? ? </button>
? ? </div>
? );
};
export default TextDemo;
新建test-demo.test.ts單元測試文件
import { fireEvent, render } from '@testing-library/react';
import TextDemo from '../../src/test-demo';
import { TestDemoMock } from './Mock/test-demo-mock';
describe('getUser', () => {
? it('mount title', async () => {
? ? const { container } = render(<TextDemo />);
? ? // 初始化期望 頁面標題為測試
? ? const title = document.body.querySelector('.test-dome-content .title');
? ? expect(title?.innerHTML).toBe('測試');
? });
? it('change title', async () => {
? ? await TestDemoMock.getUsersTitle(200);
? ? render(<TextDemo />);
? ? // 初始化期望 頁面標題為測試
? ? const title = document.body.querySelector('.test-dome-content .title');
? ? expect(title?.innerHTML).toBe('測試');
? ? // 點擊按鈕
? ? const btn = document.body.querySelector(
? ? ? '.test-dome-content .refresh-button',
? ? );
? ? fireEvent.click(btn!);
? ? await vi.waitFor(() => {
? ? ? const targetTitle = document.body.querySelector(
? ? ? ? '.test-dome-content .title',
? ? ? );
? ? ? expect(targetTitle?.innerHTML).toBe('江霧');
? ? });
? });
? it('change title error', async () => {
? ? // 模擬接口請求
? ? await TestDemoMock.getUsersTitle(201);
? ? render(<TextDemo />);
? ? // 初始化期望 頁面標題為測試
? ? const title = document.body.querySelector('.test-dome-content .title');
? ? expect(title?.innerHTML).toBe('測試');
? ? // 點擊按鈕
? ? const btn = document.body.querySelector(
? ? ? '.test-dome-content .refresh-button',
? ? );
? ? fireEvent.click(btn!);
? ? // 期望接口失敗內容為接口異常
? ? await vi.waitFor(() => {
? ? ? const title = document.body.querySelector('.test-dome-content .title');
? ? ? expect(title?.innerHTML).toBe('接口異常');
? ? });
? });
});
常見的命令
·pnpm run test : 執(zhí)行所有單元測試
·?pnpm test xxx.test.ts : 執(zhí)行某個單元測試文件
·?pnpm run coverage: 覆蓋率報告
代碼覆蓋率報告
執(zhí)行 pnpm run coverage 會生成coverage 文件夾,將其中的index.html 拖入瀏覽器中,查看具體的單元測試代碼覆蓋詳情。
E2E快速補齊單測方案
自動化錄制解決方案
·Chrome 插件 DeploySentinel Recorder
·?Chrome 插件 Headless Recorder
·?Playwrighg 官方的 CLI Playwright CLI Codegen
·?eTest 插件
最后我邀請你進入我們的【軟件測試學習交流群:785128166】, 大家可以一起探討交流軟件測試,共同學習軟件測試技術、面試等軟件測試方方面面,還會有免費直播課,收獲更多測試技巧,我們一起進階Python自動化測試/測試開發(fā),走向高薪之路
作為一個軟件測試的過來人,我想盡自己最大的努力,幫助每一個伙伴都能順利找到工作。所以我整理了下面這份資源,現(xiàn)在免費分享給大家,有需要的小伙伴可以關注【公眾號:程序員二黑】自提!
文章來源:http://www.zghlxwxcb.cn/news/detail-844761.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-844761.html
到了這里,關于Vitest 單元測試方案的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!