Writing
unit test cases is not enough, for maintaining the quality of the
application.
How
will we make sure that each scenario has been covered ? Every
branches and conditions have been covered in the unit testing ? What
if new features or functionality have been added, are they covered in
unit test cases ?
Code/Test
coverage is the answer to all the questions.
It
not only helps in maintaining the quality of the application, but
also helps developer in getting deeper understanding of the code. Most
of the times, we skip certain conditions and scenario’s assuming
that our code will execute properly as intended, but it may happen
that, based on the certain inputs it can behave differently.
What
can we do, to avoid these conditions and make sure that our code is
thoroughly tested. There are certain code coverage tools, that we can
integrate with test script.
So,
when test cases will execute, they will record the execution of our
code files and will check, what code/function/blocks have not been
executed during unit testing and will generate the coverage report.
We
can also set the threshold/limits for the code coverage tool, that how
much percentage of functions/lines/statements needs to be covered
while unit test case has been executed, and below that limits we will
fail the build.
Lets
start by adding coverage to our library, we will be using “Istanbul”.
We
will add it as a dev dependency to our library:
npm
install -D istanbul
After
adding this, we will add/modify the test script in package.json, to
add coverage.
"scripts":
{
"test"
: "istanbul cover -x
'*.test.js' node_modules/mocha/bin/_mocha --
-R spec src/api.test.js"
}
In
the above test script, we have added a “istanbul
cover -x ‘*.test.js’”,
which specifies that to record code coverage on all files, except the
files with the test.js extensions.
After that we have provided the path to the mocha executable and
specified that the reporter is “spec” which is the most commonly used reporter.
Mocha
available reporters.
Till
now we have added the code coverage recording to our library/project.
Lets
run the test script: npm
run test
We
will get the output similar to the below one, which will show the
coverage report:
Also,
a new directory has been created, with the name coverage,
and it will contain the icov report and the coverage.json file.
The
Percentage can vary based on the test cases return, in my example I
have covered all the scenarios under unit testing.
Note :
Do add the coverage directory to the .gitignore file to avoid
committing it to the source control.
Viewing
the Coverage Report In Browser:
The
generated coverage report can be viewed in the browser, navigate to
the Icov-report directory under the coverage directory, Open the
index.html file in the browser.
In
the left panel of the report, it will show the no of times the
function or statement has been executed. Also, it will show a
red cross, before the function/statement that has not been executed.
Setting the threshold/limit for the code coverage:
The
above output shows us the standard coverage report, But how can we
validate that, whenever a new feature added or existing functionality
modified, the unit testing must be done for them, to avoid any
breaking of existing functionality.
We
can set the threshold/limits for our coverage reporting and before
pushing it to source control, we can validate whether the set
threshold have been met or not, if not met we can restrict the code
to be pushed into the source control.
Istanbul
has an inbuilt module called check-coverage,
which we can use for setting the limits for the different specs.
Let’s
add another command in the script part of package.json
"scripts": {
"check-coverage":"istanbul check-coverage --statements -100 --branches - 100 --functions 100 --lines 100",
"test":"istanbul cover -x '*.test.js' node_modules/mocha/bin/_mocha -- -R spec src/api.test.js"
}
We
have added a check-coverage command in the existing script part of
package.json and have specified some limits percentage, that we
expect. We can set the threshold limits as required.
Lets
run the command, to test whether our coverage report is matching the
threshold criteria.
npm
run check-coverage
if
everything works fine then the output will be similar to the above
one.
Now,
lets try by adding some dummy function in our code and re-generate
the code coverage report.
Example
function:
function
dummy(){
console.log(“not
in use”);
}
1. Re-generate
coverage report: npm run test
We
can see that, the percentage have been dropped from 100%.
2. Check
coverage: npm run coverage
We can see the coverage validations failed as it didn’t meet the set threshold, that simply states that the newly added code has not been covered in unit testing. We can add the test case for the dummy function, and re run the coverage.
Now, we can add it to the git hooks to avoid committing the code, until the threshold has been met.
Adding Git Hooks:
We will use the ghooks npm module for adding the git hooks to our library.We will install it as a dev dependency.
npm install -D ghooks
Add the config script in the package.json file, and under config add a “ghooks” node, with the
"pre-commit" sub node:
"config": {
"ghooks": {
"pre-commit": "npm run test && npm run check-coverage"
}
}
Once, it is done and now whenever we try to commit the code, it will initially run the test script, which in turn generates the coverage report and secondly it will check, whether our coverage thresholds has been met or not.
In this way, we can assure that, whatever code has been pushed is unit tested.
In the next article, we will integrate the code coverage reporting service codecov.io , which will take reporting to the next level.
Note: Do add the coverage directory to the gitignore file to avoid committing it to the source control.
Link to my GitHub Repository