Generating Code Coverage Report Using GNU Gcov & Lcov.

Hi Readers ,

Recently I was going through online contents on how to generate report for the code in C++ project . So I curated this article thinking that it might help other who are in dire need of setting up code coverage reports.

GCOV — GNU COVerage

This is a tool developed to help user to generate reports for the C++ code written in the project . which helps you to know percentile of test cases covered

Usually project development cycle will be as

  1. You develop the software as per your pre-decided design.
  2. Write Unit test cases to check the functionality of the code written.
  3. Using these Test case written check the possible code coverage by your test cases.
  4. And generate report with the above and try to maximize the code coverage percentile by covering more test cases and hitting more lines of codes in your api’s.

I am not going to discuss all the 4 points above , as you might have already finalized your design and started coding accordingly with proper unit test cases , I will explain how to write unit test with a simple example code along with how to set up Gcov and other required tools for generating reports .

Hands Onnnnn…
Hands onnnn.

First we will write a simple program say for example Program which gives you the biggest number of given three number

main.cpp

#include<iostream>
using namespace std;
int GreatestOfThree(int a,int b,int c){
if((a>b) && (a>c)){ //for a > b and a>c case
return a;
}
else if(b>c){ //for b>c case
return b;
}
else{
return c;
}
return 0;
}
//After checking for correctness comment main function to test //main_test.cpp
int main()
{
// your code goes here
int a,b,c;
cin>>a>>b>>c;
cout<<GreatestOfThree(a,b,c);
return 0;
}

So above is our main program for finding out greatest number in the given three numbers .

now we will try to build and test whether above code works .. I am compiling my code in Linux machine so below is the command to build the main.cpp

g++ -o main main.cpp

g++ is the compiler here , -o option to mention the output file name here I am giving it as main and the source file which I want to compile i.e. main.cpp

once the above command is success without any errors in terminal

just run the binary/executable as follows

$./main 1 2 3 
$ 3

this should give out put as 3 shown above if everything is correct.

Next step is to write test cases , Here I am using Gtest, which is yet another opensource powerful library for writing Unit test cases for C++ developed by Google.

Gtest Setup

First to set up gtest in your machine you need to install gtest library ,so for this we have to get the source code first and build in our machine locally and link the libraries to standard lib path i.e. /usr/lib

Step 1 . get source from here

Method 1 . Download with one click

Method 2: Clone source from repository

if git program is not installed in your machine first get that and enter below command to get source

git clone https://github.com/google/googletest.git `

Step 2 . Extract the archived googletest folder in current directory

unzip googletest-master.zip

Step 3 . cd in to make folder within googletest directory[cd-change directory ]

cd googletest-master

Step 4 . type make , this will build the googletest library

make

Step 5 . copy built libary in the current folder to /usr/lib because compiler checks for libs in default path which is /usr/lib

sudo cp *.a /usr/lib

now you can include gtest header and start writing test cases for your code

main_test.cpp

#include "gtest/gtest.h"
#include "main.cpp"
TEST(GreaterTest,AisGreater){
EXPECT_EQ(3,GreatestOfThree(3,1,2));
};
TEST(GreaterTest,BisGreater){
EXPECT_EQ(3,GreatestOfThree(1,3,2));
};
TEST(GreaterTest,CisGreater){
EXPECT_EQ(3,GreatestOfThree(1,2,3));
};
int main(int argc,char**argv)
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

The above is the test file to test our GreatestOfThree function, but before building this file notice one thing here we are including main function in test file also so if you compile you will get error saying multiple main function , hence to test out test cases first comment the main function in main.cpp then compile it will work.

so to compile above code command is as below

g++ -o main main_test.cpp -L /usr/lib -I/usr/include

this will create an executable named main then just run that to see test cases executing in terminal

./main
[==========] Running 3 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 3 tests from GreaterTest
[ RUN ] GreaterTest.AisGreater
[ OK ] GreaterTest.AisGreater (0 ms)
[ RUN ] GreaterTest.BisGreater
[ OK ] GreaterTest.BisGreater (0 ms)
[ RUN ] GreaterTest.CisGreater
[ OK ] GreaterTest.CisGreater (0 ms)
[----------] 3 tests from GreaterTest (0 ms total)
[----------] Global test environment tear-down
[==========] 3 tests from 1 test case ran. (0 ms total)
[ PASSED ] 3 tests.

You will get output as above if everything is correct.

Generating Code Coverage Report

Now I will show how to generate coverage report for the tests written till now

So, for this task we are using tool called Gcov , Usually this will come up with GCC inbuilt so no need to install separately to use this tool one must add flags to generate reports flags to be added as follows

g++ -o main  -fprofile-arcs -ftest-coverage main_test.cpp -L /usr/lib -I/usr/include

this will generate an executable with coverage flag enabled so next you need to run the executable to generate files required for coverage report generation

./main

This will generate two types of files one is ending with extension .gcno which has info for basic block construction and line numbers this is generated because of the -ftest-coverage flag which we added while compiling with g++ command , and other type is ending with .gcda will have profiling and coverage information which is generated because of flag -fprofile-arcs in g++ command . we need both to create coverage reports .

To generate report you need to pass your test file to gcov.

gcov main_test.cpp

this will generate coverage report . which will be named as main_test.cpp.gcov since the content is not much intuitive to read by layman there is another tool which is used to generate html files of these reports which can be viewed in the browser later.

So here we will use lcov tool to check line coverage and generate html reports . For this command is as shown below.

lcov --coverage --directory . --output-file main_coverage.info

This will create a coverage report by taking .gcno and .gcda files from ‘.’ i.e. current folder where these files are present and generate an output file with coverage info in file called main_coverage.info .

Now we have coverage info lets display it in html file using below command.

genhtml main_coverage.info --output-directory out

the above command will generate html reports in output directory named as out.

once it is done you can go through the out folder and open index.html to check coverage percentile. It will display both Line coverage and Function coverage as below .

By this you can conclude how much of your code is getting covered by test cases written by you. Since I just explained you with a simple example you can go through each library/framework documentation further to know more and modify according to your project requirements .

Happy Coding

Sources:

Gtest source : https://github.com/google/googletest/tree/master/googletest

Gcov : https://gcc.gnu.org/onlinedocs/gcc/Gcov.html

Lcov : https://github.com/linux-test-project/lcov

gif image courtesy gify.com :)

I hope you liked this article .

Keep Exploring and Sharing :)

Believe Strive and Achieve .