Why do you need front-end automated testing?

Original text: https://www.wolai.com/4RCFtUJ1gqnP5eTNCkxCkB

Let's first review some well-known problems

Automated testing is born for these problems.

Access to front-end automated testing can help us expose and repair bugs in advance, reduce the cost of bugs / improve the coverage of testing, and reduce interference with the original logic of other functions.

Next, let's get to the point and introduce the front-end automated testing

Types of front-end automated testing

There are four categories:

  1. Unit test unit test is the most basic automatic test, which is used to detect the smallest measurable unit in the project, such as tool functions, basic components, etc
  2. On the basis of unit test, integration test integrates different functions to verify the overall function
  3. ui testing is not only the verification of ui design effect, but only the verification of data rendering and interaction
  4. The end-to-end test is relatively real, and the simulated real operation of the complete link is verified

Under the front-end framework of vue or react, a component test is extended. According to the granularity of components, it should actually belong to unit test or integration test.

Automated test pyramid

After introducing the types of automated tests, let's briefly compare these four tests

On top of the following, the number of test cases gradually decreases, the granularity becomes coarser, and the verification functions become changeable and complex.

At the same time, it is greatly affected by the change of demand, and the repeated interest rate is reduced

At the same time, it takes longer to write test cases and longer to execute them

On the other hand, from top to bottom, the number of initial bug s gradually decreases.

Therefore, from the perspective of number of first bug s / time to write test cases & reuse rate, unit testing benefits the most, and the more upward, the less.

This is also the reason why automated testing is used in most projects, which is at the unit testing level.

Meet the conditions for automated testing

With all that said, under what circumstances are we suitable to use front-end automated testing?

Here I have summarized some situations. In fact, only a few points need to be met

  1. The task test is clear and will not change frequently
  2. Daily post build test validation
  3. More frequent regression tests
  4. The software system interface is stable with few changes
  5. Multi platform testing, combined ergodic testing, a large number of repetitive tasks
  6. Long software maintenance cycle
  7. The project schedule pressure is not too great
  8. The development is relatively standardized and testable
  9. It has a large number of automatic test platforms
  10. Testers have strong programming ability

Some common test tools

  • Unit tests include jest and mocha
  • UI test, render, enzyme,
  • End to end (E2E Test) Cypress.io, Nightwatch.js, puppeter, TestCafe

Having said so much, unit testing is actually the most widely used and the most profitable

So later, I will tell you how to integrate unit testing into our development

How to write unit tests

Do we develop first and then supplement unit testing? Or write unit tests before development?

I believe most people who come into contact with this problem for the first time may be like me. They think it is to develop first and then supplement

But in fact, you should write unit tests first and develop code later. This pattern becomes Test Driven Development (TDD)

A very simple truth is that if there is a problem with the logic of the code you write, the unit test written according to the wrong logic can never verify the problem.

We should write our unit tests around functional design. The test content is a black box for us. We just need to verify whether it meets our design expectations, regardless of internal details. Only in this way can we ensure the stability of test cases and support refactoring

Test driven development process

  1. Quickly add a test
  2. Run the new test and find that the new test cannot pass
  3. Develop by nodes, verify while developing, and expand the test range
  4. All tests, and all passed
  5. Refactor the code to eliminate duplicate design and optimize the design structure
  6. Verify again by completing the development

Unit test steps

  1. Prepare (Arrange) to set up the test. Render components / execution conditions / prepare data
  2. Action (Act) Perform operations on the system, such as clicking buttons and triggering hook functions
  3. Assert Make sure the real results match your expectations

Unit test development case

Suppose now we want to develop a button,

Let's design the function of this button first

First, it can receive custom text, set different size s, trigger events, and then disable the function

Next, let's start writing unit tests

// tests/button.spec.js
import Button from '@/components/Button.vue'
import { mount } from "@vue/test-utils"

const BUTTON_TEXT = 'click'
describe('Button.vue', () => {
    it('render text', () => {
        const wrapper = mount(Button, {
            slots: {
                default: BUTTON_TEXT,
            },
        })
        expect(wrapper.text()).toBe(BUTTON_TEXT)
    })
    it('size', () => {
        const wrapper = mount(Button, {
            propsData: {
                size: 'small'
            }
        })
        expect(wrapper.classes()).toContain('btn-small')
    })
    test('handle click', async () => {
        const wrapper = mount(Button, {
            slots: {
                default: BUTTON_TEXT,
            },
        })
        await wrapper.trigger('click')
        expect(wrapper.emitted().click).toBeDefined()
    })
    test('handle disabled click', async () => {
        const wrapper = mount(Button, {
            slots: {
                default: BUTTON_TEXT,
            },
            propsData: {
                disabled: true
            }
        })
        expect(wrapper.classes()).toContain('is-disabled')
        await wrapper.trigger('click')
        expect(wrapper.emitted().click).toBeUndefined()
    })
})   

Complete component functions

<template>
    <button 
    :class="[
      'el-button',
        size ? 'btn-' + size : '',
      {
        'is-disabled': disabled,
      }
    ]"
    @click="handleClick">
            <span v-if="$slots.default"><slot></slot></span>
    </button>
</template>

<script>
export default {
    props:{
        size:{
            type:String,
            required:false
        },
        disabled:{
            type:Boolean,
            default:false,
            required:false
        },
    },
    methods:{
        handleClick(evt) {
            !this.disabled && this.$emit('click', evt)    
        }
    }
}
</script>

<style>
//Omit style
</style>

summary

The introduction of front-end automated testing in development can help us bring many benefits. But at the same time, a problem that can not be ignored is the cost, whether it is the time cost of writing automatic test, the cost of building platform, and the cost of project members learning automatic test. We need to consider whether the verified content is valuable and whether the automated test we worked hard to write is robust enough not to change frequently.

In short, only the right is the best.

Posted on Fri, 26 Nov 2021 09:57:12 -0500 by sqishy