In this part of the SCons series we will show how to integrate test coverage report generation for C++ codebase in SCons build system.

test coverage report sample

To generate test coverage report we use gcovr command from gcovr package so the first step is to install the package with

$ sudo apt install gcovr

command. Next we need something to test. We can use concurrent queue implementation for that purpose. This is how it’s public interface looks like

template<typename T>
class concurrent_queue
{
public:
	concurrent_queue();
	concurrent_queue(concurrent_queue const & rhs);
	void push(T x);
	void wait_and_pop(T & result);

	template <typename Rep, typename Period>
	bool wait_and_pop(T & result, std::chrono::duration<Rep, Period> const & rel_time);

	std::shared_ptr<T> wait_and_pop();
	bool try_pop(T & result);
	std::shared_ptr<T> try_pop();
	bool empty() const;

	// ...
};

Then we ofcourse need some tests so there they are

#define CATCH_CONFIG_MAIN
#include <catch.hpp>
#include "concurrent_queue.hpp"

TEST_CASE("we can push and pop elements to the queue", 
	"[concurrent_queue]")
{
	concurrent_queue<int> q;
	REQUIRE(q.empty());
	
	q.push(2);
	q.push(5);
	REQUIRE(!q.empty());

	int task;
	REQUIRE(q.try_pop(task));
	REQUIRE(q.try_pop(task));
	REQUIRE(q.empty());
}

Now we have everithing we need. To create test coverage report we need build our tests with -fprofile-arcs and -ftest-coverage compiler options and with -lgcovr linker option.

tip: go there for further options explanation

SCons build script looks this way

# generate test coverage
AddOption('--test-coverage', action='store_true', dest='test_coverage', help='enable test coverage analyze (with gcov)', default=False)

env = Environment(CCFLAGS=['-g', '-O0', '-Wall'])

if GetOption('test_coverage'):
	# https://gcc.gnu.org/onlinedocs/gcc-10.1.0/gcc/Instrumentation-Options.html
	env.Append(CXXFLAGS = ['-fprofile-arcs', '-ftest-coverage'],
		LIBS = ['gcov'])

env.Program('test.cpp')

where AddOption() call defines optional --test-coverage option in which case running test will produce test coverage analyze input as test.gcno file. The next thing we need is call gcovr to produce human readable test coverage report with this command

gcovr -r . --html-details -o coverage_report/index.html

which creates test coverage report as coverage_report/index.html.

We would like to automate as much things as possible so lets create bash script for that as coverage with this content

#!/bin/bash

COVERAGE_REPORT_PATH=coverage_report

mkdir -p ${COVERAGE_REPORT_PATH}

# run tests
./test

# then create human readable HTML report
gcovr -r . --html-details -o ${COVERAGE_REPORT_PATH}/index.html

# clean up
find  . -depth -type f -name '*.gcda' -exec rm '{}' ';'

Now all we need to do is

  • build tests with
scons --test-coverage

command and

  • run coverage script with
./coverage

command.

See test_coverage repository for full blown code, build file and script sample.