关于Jest

框架名称断言快照测试覆盖率报告仿真中文文档Github Star优点缺点
Jest36K开箱即用,配置少,文档齐全学习成本较高
Mocha×××××20.7K灵活,文档齐全配置复杂

选择jest的原因:

  1. 功能全,虽然整体学习成本较高,但可以渐进式使用部分功能
  2. 配置少,不需要从庞大的生态中挑选插件,开箱即用
  3. 虽然不像Mocha那样灵活,但是该项目不需要那么高的灵活度
  4. 有《Vue.js应用测试》讲解vue-jest和jest如何工作、测试的,Vue对jest支持也比较好,有专门的vue-jest模块,相关中文文档也多

项目配置

项目依赖版本:

  1. jest: "^27.0.6"
  2. vue-jest: "^3.0.7"(用于vue文件的编译)
  3. ts-jest: "^27.0.3"(用于ts文件的编译)
  4. ts-node: "^10.1.0"
  5. @types/jest: "^24.9.1"
  6. @vue/composition-api: "^1.0.3"(^1.0.0-beta.10与jest^27.0.6不兼容)
  7. jest-transform-stub: "^2.0.0"(处理最终结果非JS的文件)
  8. jest-serializer-vue: "^2.0.2"

配置文件 -- jest.config.ts

// jest.config.ts

import type { InitialOptionsTsJest } from "ts-jest/dist/types"

const config: InitialOptionsTsJest = {
  preset: "ts-jest",
  // 官方配置集,由于使用了TypeScript,故选用ts-jest
  globals: {
    "ts-jest": {
      tsconfig: "tsconfig.test.json"
      // Jest的ts配置文件
    }
  },
  testEnvironment: "jsdom",
  // 使用jsdom模拟真实dom
  moduleFileExtensions: ["js", "ts", "json", "vue"],
  // 如果模块路径不带后缀名,jest会按这个数组从左到右的优先顺序寻找文件
  transform: {
    "^.+\\.vue$": "vue-jest",    // vue-jest把vue文件编译成js
    "^.+\\.[tj]sx?$": "ts-jest",    // ts-jest把[tj]sx?文件编译成js
    ".+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$": "jest-transform-stub"    // 处理最终结果非JS的文件,原理是直接返回空字符串,因为最终结果非JS的文件无法测试
  },
  rootDir: "./",
  // jest配置文件或package.json所在路径
  testMatch: ["<rootDir>/js/activity/apple-gift-card/test/**/*.+(ts|tsx|js)"],
  // Jest使用glob模式来检测测试文件。默认情况下,它会在测试文件夹中查找.js、.jsx、.ts和.tsx文件,以及任何后缀为.test或.spec的文件(例如Component.test.js或Component.spec.js)。它还会找到名为test.js或spec.js的文件。
  collectCoverageFrom: [
    "<rootDir>/js/activity/apple-gift-card/components/**/**.ts",
    "!<rootDir>/js/activity/apple-gift-card/components/useLocation.ts"
  ],
  // 计算测试覆盖率的范围
  snapshotSerializers: ["jest-serializer-vue"],
  // vue的快照插件
  setupFiles: ["<rootDir>/jest-setup.ts"],
  // 初始化Jest全局环境
  transformIgnorePatterns: ["<rootDir>/node_modules/?!(vuex-composition-helpers)"]
  // 由于node_modules默认是已经transpiled的文件,所以会忽略而不走transform的编译链,加快测试速度
  // 但有些模块发布时就是Typescript或者ESM语法,node环境无法直接运行,所以要让它走transform的编译链
}

export default config

配置值字符串中的<rootDir>会被替换成rootDir的值,即"<rootDir>/js/activity/apple-gift-card"最终会变成"./js/activity/apple-gift-card"

babel配置 -- babel.config.js

// babel.config.js

module.exports = function () {

  return {
    // ...
    env: {
      test: {
        presets: ["@vue/cli-plugin-babel/preset"]
      }
    }
  }
}

在vue中引入.vue文件会出现SyntaxError: Unexpected token 'export'错误
// 原因:虽然在js、ts文件中引入.vue文件可以被vue-jest编译,但在vue中引入.vue文件需要babel引入@vue/cli-plugin-babel/preset进行编译

初始化文件 -- jest-setup.ts

// jest-setup.ts
// 导入顺序有要求:(jsdom ->) @vue/test-utils -> Vue

import VueCompositionApi from "@vue/composition-api"
require("@vue/test-utils")
const Vue = require("vue")
Vue.use(VueCompositionApi)