The purpose of unit testing is to break up your project into small units, and in each unit test try to design cases that run every branch of the code logic to. With all the unit tests running, each line of code in the project should ideally be run once, with coverage as close to 100% as possible.

Many projects put a test coverage badge on the README, for example:

Tool: Istanbul (JavaScript Code Coverage Tool)

Code coverage has four dimensions

When testing, we often care about whether all code is tested. This metric is called Code Coverage, and it has four dimensions.

  • Line coverage (line coverage) : Is every line executed?
  • Function coverage (function coverageIs every function called?
  • Branch coverage (branch coverage) : Is every if block executed?
  • Statement coverage (statement coverage) : Is every statement executed?

Lines of Source Code vs Lines of Executable Code

Lines in Line coverage mean Lines of Executable Code, not all Lines (including blank Lines) in the Source file. Executable lines: In general, each line containing a statement should be considered an executable line. Compound statements (referred to simply as blocks, enclosed in {}) are ignored (except for their contents).

function doTheThing () / / + 0{                       / / + 0
    const num = 1;      / / + 1
    console.log(num);   / / + 1
}                       / / + 0
Copy the code

The following is ignored (i.e., non-executable line, +0)

1. Nonstatement Some coverage engines will treat two of these as executable rows, and Istanbul will ignore them

  • This line contains only punctuation marks:}}; ,;
  • The name of the method (function) at definition time

Import, declaration import, declaration are treated as non-executable lines (+0), require, assignment, etc., are treated as executable lines (+1)

import { isEqual } from 'lodash';  / / + 0
const path = require('path');      / / + 1
require('jquery')                  / / + 1

let filePath                  / / + 0
const fileName = 'a.txt';     // +1

class Person {                / / + 0
    constructor (name) {      / / + 0
        this.name = name;     / / + 1
    }                         / / + 0
    
    static sayHello () {      / / + 0
        console.log('hello'); / / + 1
    }                         / / + 0
    
    walk () {}                / / + 0
}                             / / + 0

function doTheThing () / / + 0{                       / / + 0
    const num = 1;      / / + 1
    console.log(num);   / / + 1
}                       / / + 0
Copy the code

If a line has executable code, the entire line is treated as an executable line. If a statement is split into multiple lines, only the first line of the executable code block is considered executable.

Executable lines of code vs statements

In general, executable lines and statements behave the same if we follow good code specifications. However, when we put two statements on a line, we get different results.

// 2 lines, 2 statements
const x = 1;console.log(x);
Copy the code
// 1 line, 2 statements
const x = 1; console.log(x);
Copy the code

Process control

JavaScript flow control statements include:

  • if
  • white
  • The do… while
  • switch

Operator:

  • The ternary operator (condition? ExprIfTrue: exprIfFalse)

We need to ensure that each boundary case (i.e. branch) of process control is executed (overridden).

Test coverage report

The lines with the comment //+1 in the code above have either an Nx on a green background or a color block on a pink background to their left in the coverage report. So we can tell which lines of executable code are different by color

Lines of Source Code is in the green box and Lines of Executable Code is in the pink box.

Other marks

The flags that appear in the test coverage report are:

  • ‘E’ : ‘else path not taken’, indicating that the if (including else if) branch of the if/else statement is tested and the else branch is not tested
  • ‘I’ : ‘if path not taken’, as opposed to ‘E’ above, i.e. if (with else if) branch not tested
  • ‘Nx’ : Indicates the total number of times the current line of executable code has been executed
  • Pink (background color) : statement/function is not overwritten
  • Yellow (background color) : Branches are not covered

How meaningful the coverage data really is

  • Coverage data only tells you what code you tested, not whether you tested it well
  • Rather than blindly pursuing code coverage, you should find ways to design more and better cases, even if more cases have no impact on coverage

Refer to the article

Vue X Coveralls- How do I read an Istanbul Coverage Report?