Code coverage gives us an idea about what parts of the code is covered by the unit tests.
gcov
There are several open source tools available for analysing coverage. In this post, however, I will be using gcov
.
Let us consider a simple example of a calculator program. My calculator class is shown below
template<class scalarType>
class calculator
{
public:
static scalarType add(scalarType const a , scalarType const b)
{
return a+b;
}
static scalarType subtract(scalarType const a , scalarType const b)
{
return a-b;
}
static scalarType multiply(scalarType const a , scalarType const b)
{
return a*b;
}
static scalarType divide(scalarType const a , scalarType const b)
{
return a/b;
}
static scalarType abs(scalarType const a)
{
if(a<scalarType(0))
{
return -a;
}
return a;
}
};
There are several public functions that emulates the functionality of a calculator. Ideally, one would like to write a unit test corresponding to each of these functions so that the code is robust. The code coverage tools help you understand how much of your code is covered by the test programs. Now let us write a test program for the add
function as shown below
#include <calculator.hpp>
int main(void)
{
if( calculator<double>::add(double(1.),double(2.)) != double(1.)+double(2.) )
{
return 1;
}
return 0;
}
If this is the only test program you have, then the code coverage tools will tell you that the your code is not completely covered. Now let us consider unit tests for another function abs
.
if( calculator<double>::abs(double(-1.)) != double(1.) )
{
return 1;
}
Imagine that this is the only test function for the abs
function. We then know that the test will not go beyond the if
clause. This is where code coverage tools can be helpful. Let us see what the codecov.io tells us about the testing. Below is a screenshot of the coverage report.
As we can see the tests missed the return a
statement at the bottom abs
function. Therefore, ideally, we require another test function like
if( calculator<double>::abs(double(1.)) != double(1.) )
{
return 1;
}
If both test functions are present we can be sure that the abs
function is reliable.
Setting up a codecov
report using TravisCI
If your code is under a continuous integration platform, we can easily integrate the code to the a coverage platform like codecov. All you have to do is add a few lines in the .travis.yml
file. Below is an example
script:
- make testCalculator
- ./Calculator/testCalculator
- gcov Calculator/testCalculator --object-directory=Calculator/CMakeFiles/testCalculator.dir/testCalculator.cpp.gcno
- ls -la
after_success:
- bash <(curl -s https://codecov.io/bash)
The next steps are
- make an account in codecov and
- add your repository to the dashboard.
If you are linking your github, then adding a public repository is straightforward. My example repository can be found here.