Generating Code Coverage with Qt 5 and GCOV on Mac OS
We should never be too busy to not test our code.
We already know that tests help us to find bugs, improve code and performance, amongst other benefits. But how can we know if our tests are covering the major part of the code? Is it covering all possible conditions? It is very hard to say by just looking at the test cases. So, we should use code coverage tools to improve our tests and make sure it is covering all or almost all possibilities.
Ok, but the objective of this story is not to discuss why or when we should implement tests and measure the code coverage. The aim of this story is to show how to measure the code coverage using Qt 5, GCOV and LCOV on Mac OS.
Ok, but what are GCOV and LCOV?
GCOV: is used to analyze code coverage — which lines of code have actually been executed while running an application.
LCOV: is a tool that can produce HTML reports from the GCOV output.
We can use these tools to measure the code coverage of our unit tests on Qt Creator.
Before start this tutorial, let’s take a quick look at the versions of the applications/tools I’m using:
Note: It probably works with other Qt versions.
First of all, let’s write some code. This is a simple namespace which provides some calculation functions:
The functions names are self-explanatory.
Before implementing the tests, let’s configure our project to include the test library and set the coverage flags. In the PRO file, let’s define it as follow:
With our code implemented and the project configured, let’s implement some tests:
The TestSuite class is used to add derived classes to a static list of tests which will be used to run the tests when the derived classes are instantiated. Each test suite will derive from this class.
Now, let’s implement a really simple test for each function from the Calculator namespace:
These test functions will be automatically run by the Qt Test Library.
Running the tests
In the main function, we need to run each test suite and keep track how many tests have failed:
Now, we can build and run the project and get the results:
Oooops! Something went wrong!
Woow, it was my mistake. The addition function is subtracting!
It was on purpose, believe me. :)
As we can see, when a test fails it shows the test function name, the actual value, and the expected value, so it is easy to find out what is wrong with our code or test case.
Let’s fix the addition function in the calculator.cpp file:
Now, let’s build and run it again:
Congratulations, all tests have passed.
If you take a look at the build directory, you will find some GCNO and GCDA files. These files are automatically generated by the GCOV when using the coverage flags.
With the GCNO and GCDA files generated, let’s use the LCOV and GenHTML tools to generate a visual output of the code coverage. To do so, we will use the following shell script:
You must change the SRC_DIR variable to the build directory.
By running this script in the terminal (I’m using iTerm) with sh runCoverage.sh, the following page load in your browser:
This page is the code coverage report and it shows the total lines of code, the number of covered lines of code, the total number of functions and the total number of covered functions for each file.
By clicking on the calculator.cpp file we will find the following page:
It shows the calculator code and which lines the tests are covering.
But wait, the multiplication function is not being tested. By quick looking at the calculatortester.cpp file we can find out that we haven’t implemented a test for the multiplication function, so let’s implement it.
Now, our calculatortester file should look like this:
By building and running the project again, we can find the following results:
Now, let’s run the shell script again (sh runCoverage.sh):
Congratulations to us, we achieved 100% of code coverage for the calculator code.