vue+jest快速入门

1. 背景

本文介绍笔者使用jest时的使用笔记,引导读者如何使用jest实现前端的单元测试,也为笔者后续使用jest提供参考。

1.1 前置资料

1.2 重点知识

  • jest-expect
  • jest-describe
  • jest-test/it
  • jest 钩子函数
  • jest 钩子函数作用域
  • jest-mock
  • jest-snapshot

2. 快速使用

2.1 安装依赖

  • npm install jest -g
  • npm install --save-dev babel-jest @babel/core @babel/preset-env

2.2 创建jest.config.js

示例

module.exports = {
  verbose: true,
  collectCoverage: true,
  collectCoverageFrom: [
    '**/*.{js,ts}',
    '!**/node_modules/**',
    '!**/__mocks__/**',
    '!**/__tests__/**',
    '!**/build/**',
    '!**/vendor/**',
    '!e2e/**',
  ],
  coverageDirectory: 'coverage',
  clearMocks: true,
  moduleFileExtensions: ['js', 'ts'],
  roots: ['<rootDir>/__tests__'],
  testMatch: ['**/__tests__/**/*.test.[jt]s'],
  testPathIgnorePatterns: ['/node_modules/'],
  moduleNameMapper: {
    '^@root/(.*)$': '<rootDir>/$1',
    '^@src/(.*)$': '<rootDir>/src/$1',
    '^@mocks/(.*)$': '<rootDir>/__mocks__/$1',
    '^@electron/(.*)$': '<rootDir>/electron/$1',
  },
  watchPathIgnorePatterns: ['coverage'],
  watchPlugins: [
    'jest-watch-typeahead/filename',
    'jest-watch-typeahead/testname',
  ],
}

2.3 添加运行命令

package.json中添加运行命令:

{
  "scripts": {
    "jest": "jest --watch",
    "jest-updateSnapshot": "jest --updateSnapshot",
    "jest-coverage": "jest --coverage"
  }
}

特别注意:
如项目没有使用git/hg--watch将无法使用,请使用--watchAll代替。

2.4 在 nodejs 中使用

2.5.1 配置文件示例

// jest.config.js

module.exports = {
  verbose: true,
  collectCoverage: true,
  collectCoverageFrom: [
    '**/*.{js,ts}',
    '!**/node_modules/**',
    '!**/__mocks__/**',
    '!**/__tests__/**',
    '!**/build/**',
    '!**/vendor/**',
    '!e2e/**',
  ],
  coverageDirectory: 'coverage',
  clearMocks: true,
  moduleFileExtensions: ['js', 'ts'],
  roots: ['<rootDir>/__tests__'],
  testMatch: ['**/__tests__/**/*.test.[jt]s'],
  testPathIgnorePatterns: ['/node_modules/'],
  moduleNameMapper: {
    '^@root/(.*)$': '<rootDir>/$1',
    '^@src/(.*)$': '<rootDir>/src/$1',
    '^@mocks/(.*)$': '<rootDir>/__mocks__/$1',
    '^@electron/(.*)$': '<rootDir>/electron/$1',
  },
  watchPathIgnorePatterns: ['coverage'],
  watchPlugins: [
    'jest-watch-typeahead/filename',
    'jest-watch-typeahead/testname',
  ],
}

2.5.2 测试示例

示例:

// demo.js
module.exports = class Demo {
  static isTrue () {
    return true
  }
}

// demo.test.js
const Demo = require('@src/demo')

describe('Demo', () => {
  beforeEach(() => {})

  afterEach(() => {})

  beforeAll(() => {})

  afterAll(() => {})

  test('isTrue', async () => {
    expect(Demo.isTrue()).toBeTruthy()
  })
})

2.5 在 vuejs 中使用

2.5.1 安装依赖

  • npm install --save-dev @vue/test-utils vue-jest babel-jest @babel/core @babel/preset-env

2.5.2 配置文件示例

// jest.config.js

module.exports = {
  verbose: true,
  moduleFileExtensions: ['js', 'ts', 'vue'],
  collectCoverage: true,
  collectCoverageFrom: [
    '**/*.{js,ts,vue}',
    '!**/node_modules/**',
    '!**/__mocks__/**',
    '!**/__tests__/**',
    '!**/build/**',
    '!**/vendor/**',
    '!e2e/**',
  ],
  coverageDirectory: 'coverage',
  collectCoverageFrom: ['**/*.{js,ts,vue}', '!**/node_modules/**'],
  clearMocks: true,
  transform: {
    '.*\\.(vue)$': 'vue-jest',
    '.*\\.(js)$': 'babel-jest',
  },
  roots: ['<rootDir>/__tests__'],
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1',
    '^@src/(.*)$': '<rootDir>/src/$1',
    '^@mocks/(.*)$': ['<rootDir>/__mocks__/$1'],
  },
  testEnvironment: 'jsdom',
}

2.5.3 测试示例

describe('', () => {
  beforeEach(() => {})

  afterEach(() => {})

  beforeAll(() => {})

  afterAll(() => {})

  test('readJSON', async () => {})
})

2.6 测试覆盖率

2.6.1 Statements

语句覆盖率(statement coverage):是不是每个语句都被执行了。

2.6.2 Branches

分支覆盖率(branch coverage):是不是每个 if 代码块都被执行了。
JavaScript 函数参数的默认值也属于 Branches,比如:

// src/get-options.js

module.exports = function getOptions (port = 8080) {
  return {
    port,
  }
}

// __tests__/get-options.test.js
const getOptions = require('@src/get-options')

describe('test', () => {
  beforeEach(() => {})

  afterEach(() => {})

  beforeAll(() => {})

  afterAll(() => {})

  test('getOptions default', async () => {
    const result = getOptions()
    expect(result).toMatchInlineSnapshot(`
      Object {
        "port": 8080,
      }
    `)
  })

  test('getOptions 8081', async () => {
    const result = getOptions(8081)
    expect(result).toMatchInlineSnapshot(`
      Object {
        "port": 8081,
      }
    `)
  })
})

port = 8080 就属于 Branches 的范围内。
在这里插入图片描述
在这里插入图片描述

2.6.3 Functions

函数覆盖率(function coverage):是不是每个函数都被调用了。

该指标包括各种回调函数。

// src/run-callback.js

module.exports = function runCallback (callback) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      callback()
      resolve()
    }, 1000)
  })
}

// __tests__/run-callback.test.js
const runCallback = require('@src/run-callback')

describe('test', () => {
  beforeEach(() => {})

  afterEach(() => {})

  beforeAll(() => {})

  afterAll(() => {})

  test('runCallback', async () => {
    const callback = jest.fn()
    await runCallback(callback)
    expect(callback).toHaveBeenCalled()
  }, 5000)
})

在这里插入图片描述
在这里插入图片描述

2.6.4 Lines

行覆盖率(line coverage):是不是每一行都被执行了。

3. 插件

3.1 jest-watch-typeahead

按文件名或测试名称过滤单元测试,排除干扰。

// jest.config.js
{
  watchPathIgnorePatterns: ['coverage'],
  watchPlugins: [
    'jest-watch-typeahead/filename',
    'jest-watch-typeahead/testname',
  ],
}

4. 常见问题

4.1 jest: regeneratorRuntime is not defined

修改.babelrc,示例:

{
  "presets": ["@babel/preset-env", "@vue/babel-preset-jsx"],
  "plugins": [
    "@babel/plugin-transform-runtime",
    "@babel/plugin-proposal-class-properties"
  ],
  "env": {
    "test": {
      "plugins": ["@babel/plugin-transform-runtime"]
    }
  }
}

4.2 [vue-test-utils]: window is undefined

请确认jest.config.js是否有:testEnvironment: 'jsdom'

4.3 测试 sessionStorage/localStorage

请阅读这里

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿祥_csdn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值