Skip to content

UAS Portal Unit Test Setup Tutorial

Environment

  • Node >= 16.14.0
  • Vue >= 3.0.0
  • Vite >= 4.0.0

Dependency

  • vitest: Unit test framework for frontend project.
  • @vitejs/plugin-vue: To compile Vue files so that Vitest can support .vue file testing.
  • @vue/test-utils: There are many built-in tool functions for .vue file testing, which is convenient for writing test cases for vue component.
  • jsdom: This dependency emulates browser environment by providing Browser API and supports jsdomtest environment to test files.
  • @vitest/coverage-istanbul: This dependency provides instrumented code coverage via istanbul and supports to generate test coverage reports.

Workflow

  1. Install the dependencies above.
    npm i -D vitest @vitejs/plugin-vue @vue/test-utils jsdom @vitest/coverage-istanbul
    
  2. Configure vitest in vite.config.js.
    module.exports = {
      ..., // What has configured in vite.config.js for other options
      test: {
        environment: 'jsdom',
        coverage: {
          provider: 'istanbul',
          reporter: ['text', 'json', 'html'],
          reportsDirectory: './coverage',
          perFile: true,
          lines: 80,
          functions: 80,
          branches: 80
        },
        open: true,
        include: ['__tests__/unit/**/*.{test,spec}.js']
      }
    }
    
  3. Configure lint-staged command in package.json.
    "lint-staged": {
      "*{.vue,.js}": [
        "eslint src",
        "prettier --write",
        "npm run test"
      ]
    }
    
  4. Configure the test command in package.json.
    "scripts": {
      "test:unit": "vitest",
      "coverage": "vitest run --coverage"
    }
    
  5. Test coverage will generate files, which should be ignored in .gitignore.

Fundamental

  • describe: It is used to form a scope where test cases can run without outer influence.
  • it: It is mainly used to describe a test case.
  • expect: It is used to indicate the result we expected.
  • matchers: It provides many ways for you to verify the return value you are testing. Matchers can be commonly understood as equality operations.

Development Detail

The test and the developments file have the same file directory structure. Each test file corresponds to a developement file.

For Javascript/Typescript functions, it's common to input a value, and expect to get the correct output.

For Vue component, what should be covered in test file is shown as below:

  • props: Components are expected to get props correctly when input some certain prop values.
  • computed: When changing ref values, the computed values are expected to change accordingly.
  • methods: Methods are expected to get correct output when parameters are input.
  • emits: After events are triggered, components are expected to get correct triggered time and parameters.
  • slots: When a component is mounted, the customized content is passed into it as slots, and test suites should assert whether the custom content exists or not.
  • DOM: It needs to indicate a specific dom structure or using snapshot to test general structure.

Example for indicating specific dom structure:

it('DOM test', () => {
  const wrapper = shallowMount(AppButton)
  expect(wrapper.contains('button')).toBeTruthy()
})

Example for testing general dom structure:

it('match snapshot', () => {
  const wrapper = shallowMount(AppButton)
  expect(wrapper.html()).toMatchSnapshot()
})

For Vuex modules:

  • Mutations / Getters / Actions of different modules are tested separately.
  • When testing one of them, others mock data. In fact, it is a special case for testing methods.

Coverage Criteria

There are mainly three coverage criteria: Lines Coverage, Functions Coverage, and Branches Coverage. Our code standards don't allow multiple expressions on the same line, so statements coverage and lines coverage are equal. Coverage threshold can be configured in vite.config.js.

test: {
  lines: 80,
  functions: 80,
  branches: 80,
}