vue单元测试第一篇:单元测试介绍和基本使用

2,790 阅读3分钟

为什么需要单元测试?

  • 有利于我们提前隐藏的"bug":
    • 我们一般开发完成后和后端联调时,只会把大体流程跑通,这样就把压力交给QA,但是通过接口把每种情况都测试到是很麻烦到,加入如果QA有漏测情况,就会在线上埋下隐藏的bug。
    • 对于新加的需求,我们可能对之前已有逻辑不是特别清楚,这样我们新加逻辑时,就可以通过单元测试去进一步规避修改代码带来对潜在风险
  • 代码质量:
    • 往往适合加单元测试的代码可读性更好,我们必须要复杂组件拆成更细粒度的组件,把复杂的计算拆成更细粒度的工具模块才能更适合添加单元测试。

什么场景需要加单元测试?

  • ui基础组件库
  • 计算工具模块(util)
  • 简单的业务基础组件
  • store使用

覆盖的粒度

  • ui基础组件库: computed和watch属性,纯计算的方法,重要的template分支,事件的emit
  • 计算工具模块(util:100%覆盖)
  • 简单的业务基础组件:: computed和watch属性,纯计算的方法,重要的template分支,事件的emit
  • vuex:get 和mutation通过mock state来判断是否能够正常运作,action只需要通过mock commit来判断action调用是否能功能调用正常的mutation

vue单元测试工具介绍

  • 测试框架 jest:jestjs.io/ 常用的单元测试框架是 jasmine ,Mocha + Chai,不同于这些测试框架,jest 的集成度更高,提供的功能也更丰富,利用好 jest 所提供的功能,能大大提升测试用例的执行效率。 Jest 特点:
    • 测试用例并行执行,更高效
    • 强大的 Mock 功能
    • 内置的代码覆盖率检查,不需要在引入额外的工具
    • 集成 JSDOM,可以直接进行 DOM 相关的测试
    • 更易用简单,几乎不需要额外配置
    • 可以直接对 ES Module Import 的代码测试
    • 有快照测试功能,可对 React 等框架进行 UI 测试
  • Vue Test Utils: vue-test-utils.vuejs.org/ 是 Vue.js 官方的单元测试实用工具库,可以实现vue组件的测试

基础环境搭建

init product

yarn init

add jest

yarn add --dev jest

添加例子

src/test1.js

function sum(a, b) {
  return a + b;
}
module.exports = sum;

src/——test__/test1.test.js

const sum = require('./sum');

test('adds 1 + 2 to equal 3', () => {
  expect(sum(1, 2)).toBe(3);
});

run

jest

支持es6

add babel

yarn add --dev babel-jest @babel/core @babel/preset-env

添加配置babel.config.js

// babel.config.js
module.exports = {
  presets: [
    [
      '@babel/preset-env',
      {
        targets: {
          node: 'current',
        },
      },
    ],
  ],
};

添加例子

src/test2.js

export const sum = function (a, b) {
  const c = 3;
  return a + b + c;
}

src/——test__/test2.test.js

import {sum} from '../test2';

test('adds 1 + 2 + 3 to equal 6', () => {
  expect(sum(1, 2)).toBe(6);
});

run

jest

重要配置说明

添加jest.config.js,这是jest默认的配置文件名,也可以允许jest是通过--config参数指定

jest --init

重要配置字段

module.exports = {
  // 是否需要自动mock模块
  automock: false,

  // 收集测试覆盖率
  // collectCoverage: false,

  // 全局变量
  // 如:
  // globals: {
  //   'ts-jest': {
  //     tsConfig: path.join(__dirname, './tsconfig.jest.json'),
  //     babelConfig: true,
  //     diagnostics: false
  //   },
  //   'vue-jest': {
  //     tsConfig: path.join(__dirname, './tsconfig.jest.json'),
  //   },
  //   FeatureFlags: {},
  // },

  // A map from regular expressions to module names that allow to stub out resources with a single module
  // 需要手动mock的模块映射表
  // 如 当在代码有有引入@test模块时 就是用__mocks__/test.js文件替代
  // moduleNameMapper: {
  //   '^@test$':  path.join(__dirname, './__mocks__/test.js'),
  // },
  

  // 测试目录,默认是当前目录,当你需要把单元测试工具和模块代码不再一个目录时 这个配置必须用到,
  // 如设置为rootDir: process.cwd() 就是把你允许测试命令当地方作为测试目录
  rootDir: null,
  
  // 这个可以用于进行一些初始化操作,如安装ui组件库
  // setupFiles: [],

  // 测试文件的格式
  // testMatch: [
  //   "**/__tests__/**/*.[jt]s?(x)",
  //   "**/?(*.)+(spec|test).[tj]s?(x)"
  // ],

  // 测试忽略的目录
  // testPathIgnorePatterns: [
  //   "/node_modules/"
  // ],

  // 文件内容的转义,如图片的转换,js ts文件的转义
  // transform: {
  //   '^.+\\.jsx?$': 'babel-jest',
  //   '^.+\\.tsx?$': 'ts-jest',
  //   '^.+\\.vue$': 'vue-jest',
  //   '\\.svg$': path.join(__dirname, './jest-transforms/fileTransformer.js'),
  // }
};

支持typescript

install

yarn add --dev ts-jest @types/jest
yarn add --dev typescript

生成配置文件

生成 tsconfig.json 配置文件

tsc --init

添加tsconfig.jest.json

{
  "extends": "./tsconfig",
  "compilerOptions": {
    "module": "commonjs"
  }
}

修改jest.config.json

  // globals: {
  //   'ts-jest': {
  //     tsConfig: './tsconfig.jest.json',
  //     babelConfig: true,
  //     diagnostics: false
  //   }
  // },
  
  // transform: {
  //   "^.+\\.(js|jsx)$": "babel-jest",
  //   '^.+\\.tsx?$': 'ts-jest'
  // }

例子

src/test3.ts

export const sum = function (a: number, b: number): number {
  const c = 3;
  return a + b + c;
}

src/——test__/test3.test.ts

import {sum} from '../test3';

test('adds 1 + 2 + 3 to equal 6', () => {
  expect(sum(1, 2)).toBe(6);
});

支持Vue组件

install

yarn add --dev vue-jest  @vue/test-utils vue-template-compiler babel-core@7.0.0-bridge.0
yarn add vue

修改jest.config.js

 globals: {
    'ts-jest': {
      tsConfig: './tsconfig.jest.json',
      babelConfig: true,
      diagnostics: false
    },
    'vue-jest': {
      tsConfig: './tsconfig.jest.json',
    },
},
transform: {
    "^.+\\.(js|jsx)$": "babel-jest",
    '^.+\\.tsx?$': 'ts-jest',
    '^.+\\.vue$': 'vue-jest'
}

例子

src/Test4.vue

<template>
    <div class="test-wrapper">
        {{message}}
    </div>
</template>

<script language="ts">
  export default {
    name: 'Test',
    props: {
      message: {
        type: String,
        default: ''
      }
    },
    methods: {
    }
  };
</script>

src/tests/test4.test.ts

// 从测试实用工具集中导入 `mount()` 方法
// 同时导入你要测试的组件
import { mount } from '@vue/test-utils'
import Test from '../test4.vue'
import {sum} from "../test3";

// 现在挂载组件,你便得到了这个包裹器
const wrapper = mount(Test, {
  propsData: {
    message: 'test'
  }
})

// 你可以通过 `wrapper.vm` 访问实际的 Vue 实例
const vm = wrapper.vm

// 在控制台将其记录下来即可深度审阅包裹器
// 我们对 Vue Test Utils 的探索也由此开始
console.log(wrapper)


test('vue components', () => {
  expect(wrapper.find('.test-wrapper').exists()).toBe(true);
  expect(wrapper.find('.test-wrapper').text()).toBe('test');
});