preface

This article is taken from the author’s road to the front of open source projects

Interested can understand, is still in writing.

The body of the

In this section, you will learn the following:

  • The role of unit tests
  • Which modules should be most unit-tested
  • Unit test learning path of React and Vue
  • How to conduct unit testing and Demo in React and Vue frameworks

Unit tests are used to test a small piece of functionality in a program, such as a function or a class. It can significantly improve the quality of your project’s code, reduce the frequency of bugs, and also facilitate code maintenance.

But the reality is that most developers don’t want to do it. Because I am so busy with development, I don’t have time to do these things.

I personally think that testing of business code should not be mandatory, as requirements change frequently. If business code is tested with high coverage, then the test cases need to be modified synchronously as requirements change. The pressure to code this way is twofold, and it probably won’t achieve the goal of a fast-paced rollout.

However, it is necessary to write unit tests for the base component libraries and common functions that you depend on. Because the content is used by multiple modules, and the underlying functionality does not change frequently, the benefits of writing unit tests are relatively high. For example, the test coverage of well-known open source projects is often higher than 90%. Open source projects with low test coverage or no tests written at all are rarely used directly in projects.

So how do we learn about this? First, no matter what technology stack you use, you need to select a test framework. Jest is one of the relatively good frameworks (used by many well-known open source projects as well), out of the box, with an in-house integration of assertion libraries, mocks, snapshots, and more. Of course, you can also choose another framework, the core is the same, but the API has changed.

Introduction to Jest

Jest is ultimately a simple framework to use and doesn’t require much study time to get started. In addition, if you want to learn how to use the framework well, the best way is actually to read the test cases of the tool library and the component library.

Here is a brief introduction to some of the important features of Jest.

assertions

The most commonly used assertion library in Jest is the internal assertion library, because we need it to test whether the output of a function is what we expect.

It is also easy to use, you can understand a test code with a little English, and you don’t even need to look at the documentation. Let’s say you expect the output of a function to be 2

// I test a piece of code and expect the function (input) to be equal to my expected output
test(Test 1 + 1 = 2.() = > {
  expect(sum(1.1)).toBe(2)})Copy the code

About this part of the content you just need to read the document can be used proficiently.

Asynchronous code testing

Fetching data asynchronously is certainly a common scenario. Asynchronous code can be written in one of two ways:

  • The callback function
  • Function returns promise

When testing asynchronous code, the data returned is usually inconclusive, so we only need to test that the asynchronous code returns data properly.

// The callback function is written with done to keep the test code waiting
test('fetch success'.done= > {
  fetch(data= > {
    expect(data.success).toBe(true)
    done()
  })
})
// Return promise ()
// We can also use await directly for functions that return promise
test('fetch success'.() = > {
  return fetch().then(data= > {
    expect(data.success).toBe(true)})})Copy the code

A Mock function

Let’s say we need to test whether a callback function is executed and whether the arguments or return values are correct.

function foo(cb) {
  cb(1)}const mockCallback = jest.fn(value= > value + 1)
// The callback is called
expect(mockCallback).toBeCalled()
// The callback function takes 1
expect(mockCallback.mock.calls[0] [0]).toBe(1)
// The callback function returns a value of 2
expect(mockCallback.mock.results[0].value).toBe(2)
Copy the code

Of course, there are many more uses for mocks. For example, to simulate return values, to track the various situations in which functions are called, read the documentation to learn more.

The snapshot

Snapshots are a useful feature when testing components to ensure that no changes to the component’s UI are made while maintaining the code.

It’s pretty simple to use:

Expect (component instance).tomatchsnapshot ()Copy the code

The above code generates a snapshot the first time it is executed, and the two are compared each time in subsequent tests.

The configuration file

Jest, like Babel, requires a configuration file to use. For Jest, you need to create a file called jest.config.js in the root directory.

Here are some common configuration options:

module.exports = {
  // File suffix
  moduleFileExtensions: ['js'.'jsx'.'json'.'vue'].// How to convert files
  transform: {
    '^.+\\.vue$': 'vue-jest'.'.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$':
      'jest-transform-stub'.'^.+\\.jsx? $': 'babel-jest'
  },
  // Ignore the file
  transformIgnorePatterns: ['/node_modules/'].// Generate the plug-in required for the snapshot
  snapshotSerializers: ['jest-serializer-vue'].// Which directories test cases need to be executed
  testMatch: [
    '**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'].// The configuration file before executing the use case
  setupFiles: ['./tests/setup.js'].// Test coverage configuration
  collectCoverage: true.coverageReporters: ['html'.'lcov'.'text-summary'].coverageDirectory: './test/coverage'.collectCoverageFrom: ['components/**/*.vue']}Copy the code

See the documentation for more configuration properties.

How to single test a utility function

For utility functions, the first point is that the function should not contain too many functions. It is best to break them up into individual functions because they are easy to test.

In addition, for utility functions, the output should be controllable, so it is easy to write single tests that only need the output of except functions.

How do I single test components

The most important thing for components is to take snapshots of each state of the component in case the code changes cause BUGS at the UI level. The rest is to test each function, such as whether the value is set correctly, whether the event is responsive, whether the logic is correct, and so on. This part of the test mainly depends on the function of the specific component.

Also, if you do statistical test coverage, you will find that Branch metrics are often the hardest to improve for components. Once you can get that up to 95% or more, the problem with this component is much less.

Practice Jest in Vue

It is recommended that you read this document after you complete the environment configuration.

This section summarizes the demo address

configuration

Whether you need to use Jest for an existing project or a new project, you can do so with Vue Cli 3.

For existing projects, simply execute a command in the project folder

vue add unit-jest
Copy the code

The scaffolding will automatically help you install the Jest configuration in your project, and you will find a new folder in your root directory

The folder contains a test case that you can run simply by running YARN Test :unit.

For new projects, select Manually Select Features during project creation and then follow the following to integrate the Jest environment.

practice

With the environment configured, let’s start a simple component test.

PS: Component testing requires the @vue/test-utils library because it is needed to help us mount components and perform a series of operations on them. Once the component is mounted, we can use Jest to assert, Mock, generate snapshots, and so on.

In the Components folder we add a new file loading.vue

<template>
  <div class="loading">
    <span class="loading__indicator" :style="style" />
    <span class="loading__text" v-show="text">{{ text }}</span>
  </div>
</template>

<script>
export default {
  props: {
    text: String.size: {
      type: Number.default: 26
    },
    indicatorColor: {
      type: String.default: "#1989FA"}},computed: {
    style() {
      return {
        width: this.size + "px".height: this.size + "px".borderColor: this.indicatorColor,
        borderBottomColor: "transparent"}; }}};</script>
Copy the code

The above code is a simple component. Passing in props completes the rendering of the entire component. There is no other logic.

The test case is also simple, with 100% test coverage achieved by comparing all props inputs and outputs.

describe('Loading.vue'.() = > {
  it('renders props.msg when passed'.() = > {
    const wrapper = mount(Loading, {
      propsData: {
        text: 'Loading'.indicatorColor: 'red'.size: 20}})const indicatorStyle = wrapper.find('.loading__indicator').element.style
    expect(wrapper.find('.loading__text').text()).toBe('Loading')
    expect(indicatorStyle.borderColor).toContain('red')
    expect(indicatorStyle.width).toContain('20px')
  })
  it('snapshot'.() = > {
    const wrapper = mount(Loading, {
      propsData: {
        text: 'Loading'.indicatorColor: 'red'.size: 20
      }
    })
    expect(wrapper).toMatchSnapshot()
  })
})
Copy the code

After the yarn test:unit command is executed, the following information is displayed

If you want to learn more about unit testing in Vue, the following materials are recommended:

  • The above documents are very detailed
  • How to test complex components
  • Vant component library, read the test cases in the Vant component library (in the Test directory for each component)

Practice Jest in React

It is recommended that you read this document after you complete the environment configuration.

This section summarizes the demo address

configuration

For new projects, if you use create-React-app, Jest is integrated internally by default, and you can see the Jest configuration in the package.json file by running the yarn eject command.

For existing projects, you can use my demo or this article to learn the configuration, so I won’t go into details here.

In addition, some students may be TS environment, so my Demo is based on TS configuration.

practice

PS: Component testing needs to use the enzyme and the enzyme adapter-React-16 libraries, because they are needed to help us mount the component and perform a series of operations on the component. Once the component is mounted, we can use Jest to assert, Mock, generate snapshots, and so on.

In addition, in view of the content of component testing and Vue is basically the same, so there is no waste of space to copy the code, the specific content can be learned in the demo.

If you want to learn more about unit testing in React, the following materials are recommended:

  • The author has a cool component library, including components and tool functions of the test
  • Ant – the design component library
  • Read the test cases in the Vant component library (in the Tests directory for each component)

conclusion

In general, there is not much to learn in unit testing on a project. A SINGLE Jest plus a library that can mount components is all you need to learn in a day.

Where you really need to spend your time is reading test cases from good third-party libraries.