Coverage detection is used to determine the integrity of a single test, and both JEST and Karma provide this functionality:

Coverage is the percentage of code executed as a percentage of total code, such as lines, branches, functions, and statements executed.

It compares the total number of coverage, including line coverage, branch coverage, function coverage, statement coverage, etc.

Doesn’t it look amazing that you can know which code is covered after executing it once? In fact, the implementation principle is relatively simple. I believe that after reading this article, you will have “That’s it? Feeling.

Principle of inquiry

Both Jest and Karama are based on the Istanbul coverage test, so let’s look at how this works.

The test code is as follows:

We execute the Istanbul instrument order:

npx istanbul instrument ./test.js -o ./out.js
Copy the code

Instrument is a function peg, which is to transparently add some code to a function.

Why did you put the stakes in? Look at the generated code and you’ll see.

So let’s format it a little bit and replace the variable names.

This is the converted code, counting the s, f, and B attributes in each statement, function, and branch.

Here’s another code:

The global variable AAA is initialized to record the following information:

  • pathPath:
  • s: the number of the statement
  • b: branch number
  • fNumber: function
  • fnMap: Function start and end positions
  • statementMap: Indicates the start and end positions of the statement
  • branchMap: Indicates the start and end location of a branch

We can see how coverage works by inserting a count code for each statement, function, and branch in a global object.

To avoid conflicts with other global variables, the object’s name is randomly generated, such as __cov_5ZoEXQ_Hbo27uXArxdm2oA, which is changed to AAA for simplicity.

We figured out that coverage depends on insertion count code, so how do we do the insertion?

Function in the pile

Insert the AST of statement, function, and branch code in front of it.

And that’s exactly what Istanbul does.

Here’s the Istanbul source code (just look at the position marked by the red line) :

Parse the code into an AST using Esprima (JS Parser) and then peg the AST.

The staking code is divided into two parts, one is the code that initializes the global object, and the other is the code that counts each branch, statement, and function.

Let’s take a look:

Initialize code pegs for global objects

Istanbul initializes the global coverState object for statistics:

The information will be recorded in this coverState when piling:

Finally, add coverState to the code as a string:

How is the AST of specific branches, statements, and functions staked?

Staking of branches, statements, functions

For pile insertion of different AST, different processing is done according to the type in the traversal process:

Then, the concrete peg is to insert an AST in front of it:

The statement in pile:

Insert the function post:

See here, we know the implementation principle of function staking, is to traverse the AST, in different positions to insert the AST count code can be done.

But some students may say, usually I did not manually generate the code after piling ah? Running the test case with Jest –coverage automatically counts and gives coverage data.

How does Istanbul make the piling transparent?

Require Hook implements transparent and non-perceptive function piling

Nodejs module loading is divided into load, extension[‘.js’] and compile.

We can do this transparently by overriding extension[‘.js’].

Istanbul does the same thing:

It does this by modifying the extension[‘.js’] method, inserting the function in it, and then executing the transformed code without the developer being aware of it.

conclusion

Both JEST and Karma implement coverage detection based on Istanbul. The principle of coverage statistics is function pegging. Counting codes are inserted into statement, function and branch codes based on AST, and transparent conversion is realized through Require Hook. As soon as the code executes, the statistics are available and the coverage rate can be calculated.

After watching it, do you feel:

Implementation of coverage detection, that’s it?