Skip to content
On this page

测试框架

目前基于 vue 项目框架采用 vue-jest

vue test

jest

文件组织结构

  1. 全局通用的配置

统一放在 test/setup.ts ,结合 jest.config 配置 setupFiles: ['./src/test/setup.ts']

示例:

import { config } from '@vue/test-utils'

config.global.mocks = { $ossPath: '' }

  1. api 的 mock 数据

文件以mocks命名,放在对应 api 文件下 ,jest 会自动识别这个文件,在测试文件中按正常 api 调用的写法即可。

  1. 测试文件

文件以tests命名,放在对应需要测试的文件下

cicd 流程

在.gitlab-ci.yml 文件中加入测试流程,每一次发布都要跑单元测试,代码以模组为例:

stages:
  - autochart
  - detect
  - test
  - build
  - deploy

...

test:unit-test:
  stage: test
  image: ${CI_IMAGE_NODE}
  only:
    - master
    - tags
  extends: .node-cache
  script:
    - yarn run test --silent
  tags:
    - ali
    - docker
    - new

代码规范

目前采用 eslint-plugin-jest( https://github.com/jest-community/eslint-plugin-jest#readme

不需要测试

  • 第三方提供的功能
  • antdesign 中的组件、vue-router 的路由跳转方法
  • 与逻辑无关的 UI
  • 布局、样式

示例

一个单元测试的结构

describe('一类测试', () => {
  let wrapper: Wrapper<Vue>

  beforeEach(() => {
    wrapper = shallowMount(component, {})
  })
  afterEach(() => {
    wrapper.destroy()
  })

  it('测试一', () => {
    expect().toBeTruthy()
  })

  it('测试二', () => {
    expect().toBeTruthy()
  })
})

异步 expect

import { nextTick } from 'vue'

const asyncExpect = (fn: () => void) => {
  return new Promise(resolve => {
    nextTick(() => {
      fn()
      resolve(0)
    })
  })
}
describe('aa', () => {
  it('aaa', async() => {
      ...
     // await wrapper.vm.$nextTick()
     // expect(getOrderInfo).toBeCalledTimes(3)
     // expect(wrapper.vm.orderStatus).toBe(3)
     await asyncExpect(() => {
      expect(getOrderInfo).toBeCalledTimes(3)
      expect(wrapper.vm.orderStatus).toBe(3)
    })
  })
})

自定义匹配——可以抽取出一些相同结构的 matchers


expect.extend({
  innerHtmlToBe(ele, str) {
    const pass = ele.element.innerHTML === str
    if (pass) {
      return {
        message: () => 'success',
        pass: true
      }
    } else {
      return {
        message: () => 'fail',
        pass: false
      }
    }
  }
})

describe('AlertTest', () => {
  test('设置title时,能正确显示title', async () => {
    const wrapper = shallowMount(Alert, {
      props: {
        title: 'aa'
      }
    })

    // expect(wrapper.find('.alert-title').element.innerHTML).toBe('aa')
    expect(wrapper.find('.alert-title')).innerHtmlToBe('aa')
  })
})

ts 中需要同步配置该 matchers 类型

namespace jest {
    interface Matchers<R> {
      innerHtmlToBe(s: string): R
    }
  }

MIT License.