【前端】前端单元测试、覆盖率测试工具Vitest入门指南

2024-03-01 1197阅读

温馨提示:这篇文章已超过389天没有更新,请注意相关的内容是否还可用!

前言

单元测试的重要性不言而喻,可以很大程度的减少一些bug的产生。在前端项目中,有很多用于单元测试的工具,如最常见的Jest。但对于由vite构建的前端项目而言,使用vite配套的vitest会更加方便、舒适。官方文档是最好的入门方式,这篇文章记录在入门过程中可能遇到的一些问题,方便想了解的人更快速的上手。本文暂时只介绍单元测试和覆盖率测试的使用方法。

安装与配置

安装方法

  • npm

    npm install -D vitest

  • yarn

    yarn add -D vitest

    基础配置

    在package.json文件中,添加以下代码:

    {
      "scripts": {
        "test": "vitest"
      }
    }
    

    测试Vitest是否能正常工作

    按照官方文档的示例,准备两个文件sum.ts和sum.test.ts(可以在项目根目录下创建一个test文件夹,专门用来存放测试文件):

    // sum.ts
    export function sum(a, b) {
      return a + b
    }
    
    // sum.test.ts
    import { expect, test } from 'vitest'
    import { sum } from './sum'
    test('adds 1 + 2 to equal 3', () => {
      expect(sum(1, 2)).toBe(3)
    })
    

    然后,在终端中运行指令npm run test(或者yarn test)。

    如果没有意外,那么将出现以下结果:

    【前端】前端单元测试、覆盖率测试工具Vitest入门指南

    关键字解释

    如果你之前没有用过Jest,那么对于sum.test.ts文件中的test、expect、toBe方法,肯定一头雾水。

    1. test(别名为it)

      test方法是用于编写单元测试的函数。test方法接受两个参数:测试名称和测试函数。语法如下:

    test(name: string, testFn: Function, timeout?: number | TestOptions): Promise;
    
    • name

      接收一个字符串,作为测试的名称显示在控制台中。一般用来描述该项测试的内容。

    • testFn

      是一个异步或同步的函数,用于执行测试逻辑和断言。

    • timeout

      可选参数,用于设置测试的超时时间(以毫秒为单位)。如果测试在超时时间内没有完成,则会失败并抛出错误。

      1. expect

        expect方法是用于创建断言的函数。断言是一种用于验证代码的行为和输出是否符合预期的方式。

        expect 方法的基本语法如下:

      expect(actual).matcher(expected)
      

      其中,actual是一个表达式或变量,表示要检查的实际值。matcher是一个函数,表示要使用的比较方法。expected是一个值或对象,表示期望的结果。

      在本例中,expect(sum(1, 2)).toBe(3)表示使用expect方法来测试sum函数是否能正确地将两个数字相加。此处使用 toBe来进行断言,这是Vitest提供的一个匹配器函数,用于比较实际值和期望值是否严格相等。

      配合IDE使用

      Vitest在各大主流前端IDE中都有对应的插件供开发者更方便的使用测试功能,这里以vscode为例,直接在插件市场搜索Vitest,点击安装即可。

      【前端】前端单元测试、覆盖率测试工具Vitest入门指南

      然后打开sum.test.ts文件,可以看到test方法的那一行的左边出现了一个图标:

      【前端】前端单元测试、覆盖率测试工具Vitest入门指南

      点击该图标即可运行该文件下的测试代码,右键该图标可以进行更多选择,比如调试。

      实际应用

      测试文件准备

      所谓单元测试,指的是对最小测试单元进行测试。比如在项目中写了一个计算文本宽度的方法,方法写好之后如果直接拿过去用,除非是经过验证的现有方法,否则是容易出现处理上的漏洞的。因此我们可以把这个方法单独提取出来,放到测试文件夹中。

      1. 首先,在项目根目录下创建一个test文件夹,并在其下创建两个文件,分别为util.ts、util.test.ts。打开util.ts,写入以下代码:
      export function getTextWidth(str: string | number): number {
      	if (!str) return 0;
      	// 如果str是数字,则转换为字符串
      	if (typeof str === 'number') {
      		str = str.toString();
      	}
      	if (str.length = 'A' && char = 'a' && char 
      			// 如果是英文字符,为字符分配10个单位宽度
      			flexWidth += 10;
      		} else if (char = '\u4e00' && char 
      			// 如果是中文字符,为字符分配15个单位宽度
      			flexWidth += 15;
      		} else if (regx.test(char)) {
      			flexWidth += 9;
      		} else {
      			// 其他种类字符,为字符分配7个单位宽度
      			flexWidth += 7;
      		}
      	}
      	return flexWidth;
      }
       expect, test, describe } from 'vitest'
      import { getTextWidth } from './utilTemp'
      describe('getTextWidth function', () = {
        // test for empty string
        test('returns 0 if the input is an empty string', () => {
          expect(getTextWidth('')).toBe(0)
        })
        // test for single character
        test('returns 40 if the input is a single character', () => {
          expect(getTextWidth('a')).toBe(40)
          expect(getTextWidth('中')).toBe(40)
          expect(getTextWidth(1)).toBe(40)
        })
        // test for numbers
        test('returns the correct width for numbers', () => {
          expect(getTextWidth(123)).toBe(27)
          expect(getTextWidth(3.14)).toBe(34)
          expect(getTextWidth(-100)).toBe(34)
        })
        // test for english characters
        test('returns the correct width for english characters', () => {
          expect(getTextWidth('Hello')).toBe(50)
          expect(getTextWidth('World')).toBe(50)
          expect(getTextWidth('Hello World')).toBe(107)
        })
        // test for chinese characters
        test('returns the correct width for chinese characters', () => {
          expect(getTextWidth('你好')).toBe(40)
          expect(getTextWidth('世界')).toBe(40)
          expect(getTextWidth('你好世界')).toBe(60)
        })
        // test for mixed characters
        test('returns the correct width for mixed characters', () => {
          expect(getTextWidth('Hello你好')).toBe(80)
          expect(getTextWidth('World世界')).toBe(80)
          expect(getTextWidth('Hello World你好世界')).toBe(167)
        })
      })
      

      然后在vscode里面点击运行,或者在命令行里执行yarn test(npm run test),就能看到结果了:

      【前端】前端单元测试、覆盖率测试工具Vitest入门指南

      测试覆盖率

      代码覆盖率是一种用于评估代码的质量和完整性的指标,它表示代码中有多少比例被测试用例所覆盖。测试覆盖率的工具可以帮助开发者生成和查看覆盖率报告,从而发现代码中的潜在问题和改进点。

      1. 先去package.json中添加以下代码:
      {
        "scripts": {
          "coverage": "vitest run --coverage"
        }
      }
      
      1. 安装覆盖率工具

        Vitest提供两种覆盖率工具:v8和istanbul。这两种工具的区别感兴趣可以自己去了解,这里不做说明。默认情况下,Vitest启用 v8,因此需要安装v8工具:

        yarn add -D @vitest/coverage-v8。

      2. 开启覆盖率测试

        打开vite.config.ts,在defineConfig下添加以下配置:

      {
      	test: {
      		reporters: ['default', 'html'],
      		coverage: {
      			enabled: true,
      			provider: 'v8',
      			cleanOnRerun: true,
      			reporter: ['text', 'json', 'html'],
      		},
      	},
      }
      

      这里需要说明的是,官方说在vite.config.ts的顶部添加三斜线指令/// 即可在vite的配置文件里添加Vitest的选项,但我试了,会报类型错误,所以我直接把defineConfig的导入改为了import { defineConfig } from 'vitest/config';。或者你可以单独新建一个vitest.config.ts文件进行配置。

      配置完成后,运行yarn test,就能看到结果:

      【前端】前端单元测试、覆盖率测试工具Vitest入门指南

      可以看到,utilTemp.ts这一行对应的列都为100,说明覆盖率测试通过。(当然不一定非得是百分百才算通过,但一般规定至少得90%)

      通过UI查看结果

      在命令行里查看测试结果相对来说不够直观,因此Vitest提供一个漂亮的 UI 界面来查看并与之交互。Vitest 的 UI 界面是可选的,你可以通过以下方式安装:

      yarn add -D @vitest/ui
      

      或者

      npm i -D @vitest/ui
      

      安装完后,执行指令:yarn test --ui,就会开启一个服务器,然后会在浏览器里自动打开Vitest UI的界面:

      【前端】前端单元测试、覆盖率测试工具Vitest入门指南

      点击右侧的文件,可以详细查看测试代码的覆盖情况,绿色代表已覆盖,红色代表未覆盖,说明需要修改测试代码以保证全覆盖。

      【前端】前端单元测试、覆盖率测试工具Vitest入门指南

      结语

      至此,有关Vitest的入门操作已介绍完毕。当然,Vitest的功能远不止如此,更多的功能,比如组件测试、快照测试、以及更多的配置、API等,请自行转到官方文档了解。

VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]