Vitest 单元测试方案

简介

  Vitest 是一个面向 Vite 的极快的单元测试框架。它利用了 Vite 的优势,提供了一种全新的测试体验。本文将介绍如何在项目中集成和使用 Vitest 进行单元测试。

  安装 Vitest

  npm install -D vitest

  配置 Vitest

  在项目根目录下创建 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公共文件

  在项目根目录下创建setup-test.ts文件,用于统一处理定时器,原生事件,以及在vitest环境下无法模拟的事件

  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接口

  · 初始化单元测试环境内时间

  单元测试分类

  · 单元测试:主要是对项目里的最小 组件 或模块进行测试,一般是在非浏览器环境下的测试

  · 集成测试:一般是对单元测试下的多个最小单元组成的较大 组件 或模块进行小型的组合测试,一般是在非浏览器环境下的测试。

  · 端到端 测试 (E2E) : 从用户的视角出发,基于整个页面或者应用,模拟用户操作测试,一般是在浏览器环境下的测试

  如何编写 单元测试

  在项目src目录平级的位置,新建tests文件,tests文件夹下新建mocks文件夹

  · mocks下主要存放对应单元测试模拟数据的文件

  · 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 : 执行所有单元测试

  · pnpm test xxx.test.ts : 执行某个单元测试文件

  · pnpm run coverage: 覆盖率报告

  代码覆盖率报告

  执行 pnpm run coverage 会生成coverage 文件夹,将其中的index.html 拖入浏览器中,查看具体的单元测试代码覆盖详情。

  E2E快速补齐单测方案

  自动化录制解决方案

  ·Chrome 插件 DeploySentinel Recorder

  · Chrome 插件 Headless Recorder

  · Playwrighg 官方的 CLI Playwright CLI Codegen

  · eTest 插件

作为一个软件测试的过来人,我想尽自己最大的努力,帮助每一个伙伴都能顺利找到工作。所以我整理了下面这份资源,现在免费分享给大家,有需要的小伙伴可以关注【公众号:开心螺蛳粉】自提!

软件测试面试文档

我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。在这里插入图片描述

在这里插入图片描述

行动吧,在路上总比一直观望的要好,未来的你肯定会感谢现在拼搏的自己!如果想学习提升找不到资料,没人答疑解惑时,请及时加入群:1150305204,里面有各种测试开发资料和技术可以一起交流哦。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/499824.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

AcWing-毕业旅行问题

731. 毕业旅行问题 - AcWing题库 所需知识&#xff1a;二进制状态压缩&#xff0c;dp 思路&#xff1a;Hamilton最小路径的变种&#xff0c;如果Hamilton最小路径不懂可以看看我这篇文章AcWing—最短Hamilton路径-CSDN博客 搞懂了Hamilton之后这题就很简单了&#xff0c;遍历…

【51单片机入门记录】Onewire单总线协议 温度传感器DS18B20概述

一、温度传感器DS18B20概述 &#xff08;1&#xff09;数字化温度传感器 美国DALLAS半导体公司的数字化温度传感器DS1820是世界上第一片支持“一线总线”接口的温度传感器。一线总线独特而且经济的特点&#xff0c;使用户可轻松地组建传感器网络&#xff0c;为测量系统的构建…

一、图片隐写[Stegsolve、binwalk、010editor、WaterMark、BlindWaterMark、文件头尾]

工具配置 1.Stegsolve 工具地址&#xff1a;http://www.caesum.com/handbook/Stegsolve.jar 解释&#xff1a;该工具需要安装jar包后才能配合使用&#xff0c;下面同时会给出快速打开工具的代码&#xff0c;需要两个文件&#xff0c;启动的时候启动vbs文件 start.bat java …

【笔记本开热点给手机用,手机一直显示正在获取ip地址,然后连接不上的解决方法】

解决方法 控制面板\网络和 Internet\网络连接 查看是否有设备是固定ip,将其改成自动获取ip地址 如果你还没有解决&#xff0c;那么继续看 肯定是你装了vmware,vmware会生成vmnet1和vmnet8两个网段&#xff0c;这两个网段和共享的网段冲突了&#xff0c;所以需要将这两个网段…

4T第十四届省赛模拟2

一、Seg 温度读取&#xff1a; ①温度 温度读他读出来就是有精度的所以自带小数 我们读取的时候直接强制类型转换读它的各个位也不会丢失精度 ②电压 电压是你人为的/51.0了&#xff0c;从char->float->char所以会有精度丢失 所以要用原始数据来换算 在原始数据上多…

qt窗口的应用与pyinstaller打包APP操作

3月29日 qt打包APP操作 1 先在windows shell 中下载打包软件Pylnstaller pip install pyinstaller2 先进入py项目所在的位置&#xff0c;再执行以下代码(我用的qt版本是PySide6可以根据自己的情况修改) pyinstaller s02.py --noconsole --hidden-import PySide6.QtXml3 因为…

GEE22:基于目视解译的土地利用分类(随机森林监督分类)

采样点信息&#xff1a; 设置一下采样点参数&#xff1a; 代码&#xff1a; //设置研究区位置 var table ee.FeatureCollection("users/cduthes1991/boundry/China_province_2019"); var roi table.filter(ee.Filter.eq(provinces,beijing)); Map.centerObjec…

Machine Learning机器学习之数据可视化

目录 前言 一、 数据预处理与清洗 二、常见可视化技术 三、可视化工具和平台 博主介绍&#xff1a;✌专注于前后端、机器学习、人工智能应用领域开发的优质创作者、秉着互联网精神开源贡献精神&#xff0c;答疑解惑、坚持优质作品共享。本人是掘金/腾讯云/阿里云等平台优质作者…

MES系统怎么解决车间生产调度难的问题?

MES系统三个层次 1、MES决定了生产什么&#xff0c;何时生产&#xff0c;也就是说它使公司保证按照订单规定日期交付准确的产品&#xff1b; 2、MES决定谁通过什么方式&#xff08;流程&#xff09;生产&#xff0c;即通过优化资源配置&#xff0c;最有效运用资源&#xff1b; …

PCI总线管脚定义(引脚定义)

文章目录 1&#xff1a; 参考资料的链接2: 图片说明3&#xff1a;PCI文字说明每日好图 1&#xff1a; 参考资料的链接 PCI bus pinout PCI三种标准引脚信号定义 PCI bus pinout 2: 图片说明 A面和B面正反 PCI Universal Card 32/64 bit ----------------------------------…

同事们希望我拥有博士学位,但资历并不是一切

罗伯特纽贝克 “你太聪明了&#xff01;你为什么没有博士学位&#xff1f;这个熟悉的问题被当作赞美&#xff0c;但总感觉像是一记耳光。我已经在该组织工作了 2 周&#xff0c;每个人似乎都喜欢我正在做的工作、我带来的观点以及我为我的团队设想的方向。但只有一个小问题&am…

打PTA (15分)(JAVA)

目录 题目描述 输入格式&#xff1a; 输出格式&#xff1a; 输入样例&#xff1a; 输出样例&#xff1a; 题解 题目描述 传说这是集美大学的学生对话。本题要求你做一个简单的自动问答机&#xff0c;对任何一个问句&#xff0c;只要其中包含 PTA 就回答 Yes!&#xff0c;其…

机器学习 - 手动实现 ReLU 和 Sigmoid

直接上代码 import torch import matplotlib.pyplot as pltA torch.arange(-10, 10, 1, dtypetorch.float(32)) def relu(x):return torch.maximum(torch.tensor(0), x) plt.plot(relu(A))结果如下&#xff1a; import torch import matplotlib.pyplot as pltA torch.aran…

FPGA Artix7 Bootloader App Python升级

文章目录 软硬环境复现官方 srec_spi_bootloader例子简介Vivado硬件部分存储划分Vitis 嵌入式 BootVitis 嵌入式 Appelf转换srec合并boot和app得到mcs文件下载测试过程分析 基础知识BIT MCS HEX BINBit SwappingSREC 文件格式Vivado约束 串口Boot地址划分链接脚本修改Github Li…

1.Netty介绍及NIO三大组件

Netty网络编程Netty的底层是NIO&#xff08;非阻塞IO&#xff09;&#xff0c;常用的多线程和线程池使用的是阻塞IO&#xff0c;其效率并不高。支持高并发&#xff0c;性能好高性能的服务端程序、客户端程序 NIO三大组件 一、Channel 读写数据的双向传输通道 常见的传输通道…

Taskflow 简单使用

Hello World #include <taskflow/taskflow.hpp>int main() {tf::Executor executor; tf::Taskflow taskflow;// 返回一个std::tuple<tf::Task, tf::Task, tf::Task, tf::Task> auto [A, B, C, D] taskflow.emplace([](){std::cout<<"A"<<s…

金三银四面试题(六):对象大小知多少

对象和数组在JVM如何在堆中布局&#xff1f;更常见地问法就是对象头都包含哪些信息 在JVM中对象和数组尽管都是连续的内存块。但在堆内存中的布局方式有些不同。 对象的组成 对象在JVM中可以分为三个部分&#xff0c;对象头&#xff08;Header&#xff09;&#xff0c;实例数…

SoC芯片的DVFS技术详解

​A72训练营很多同学问DVFS技术怎么实现的&#xff0c;这里小编就和大家掰扯掰扯SoC芯片的DVFS技术吧。 1. DVFS技术介绍 DVFS&#xff08;Dynamic Voltage and Frequency Scaling&#xff09;即动态电压频率调节技术&#xff0c;是一种高效的低功耗技术&#xff0c;它通过动态…

初始化脚手架

说明: 1 --- Vue脚手架是Vue官方提供的标准化开发工具&#xff08;开发平台&#xff09; 2 --- 最新的版本是 4.x 3 --- 文档 Vue CLI 具体步骤: 1 --- 如果下载缓慢请配置npm淘宝镜像npm config set registry http://registry.npm.taobao.org 2 --- 全局安装 vue/cli npm ins…

Apache Kafka + 矢量数据库 + LLM = 实时 GenAI

公众号&#xff1a;Halo咯咯 生成式人工智能 (GenAI) 支持先进的人工智能用例和创新&#xff0c;但也改变了企业架构的外观。大型语言模型 (LLM)、向量数据库和检索增强生成 (RAG) 需要新的数据集成模式和数据工程最佳实践。 Apache Kafka 和 Apache Flink 的数据流在大规模实时…