Code coverage with gcov and cmake.

Why to measure code coverage?

Code coverage is well established in industry metrics of a code quality (well kind of). At the end it is all about tests quality, because you can have tests that do not test anything, they just generating code coverage, to satisfy process. But this is not a reason not to measure. Code coverage will show you:

  • untested code.
  • weak points of implementation
  • bad “monolith” code design
  • dead code

So lets add code coverage measurements into our cmake project.

Tools

We will use gcov, and cmake.
Code of template cmake project can be found on github.
You can read about gcov here.

Understanding gcov

Simplifying how gcov works, we can tell that there is no gcov, there is a set of additional instructions that are placed by a compiler (a gcc in this case) into our executable in order to generate code execution map. If line of code was executed, then it will be marked as executed, if not than not. This tells us very important thing.  We do not want this in a production binary. We need to do this optional, on the level of build configuration.

Human readable output.

To parse gcov statistics, and present them in a human readable way we will use a gcovr.

Cmake module.

As code instrumentation need to be set for all of our code, we can set entire coverage measurement settings inside a module.

if(USE_GCOV)
    include(ExternalProject)
    ExternalProject_Add(gcovr
        URL https://github.com/gcovr/gcovr/archive/3.2.zip
        URL_HASH SHA1=7411d3989116c5fa65519ee1a54237df16944ad2
        CONFIGURE_COMMAND ""
        BUILD_COMMAND ""
        INSTALL_COMMAND ""
    )

    ExternalProject_Get_Property(gcovr source_dir)
    SET(GCOVR ${source_dir}/scripts/gcovr)

    SET(GCC_COVERAGE_COMPILE_FLAGS "-fprofile-arcs -ftest-coverage")
    SET(GCC_COVERAGE_LINK_FLAGS "-lgcov")
    SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}" )
    SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_LINKER_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}" )               

    add_custom_command(OUTPUT _run_gcovr_parser
    POST_BUILD
    COMMAND ${GCOVR} -r ${CMAKE_SOURCE_DIR}/src --object-dir=
    ${CMAKE_BINARY_DIR} -e test_*
    COMMAND ${GCOVR} -r ${CMAKE_SOURCE_DIR}/src --object-dir=
    ${CMAKE_BINARY_DIR} --branches --exclude-unreachable-branches -e test_*
    WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
    add_custom_target (coverage DEPENDS _run_gcovr_parser)
endif(USE_GCOV)

We need to include module inside our main cmake file CMakeLists.txt.

 list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules)
 include (gcovr)
 

Usage

cmake -DUSE_GCOV=yes ../
make all
make test
make coverage
------------------------------------------------------------------------------
GCC Code Coverage Report
Directory: /home/sopniews/work/priv/template_cmake_project/src
------------------------------------------------------------------------------
File Lines Exec Cover Missing
------------------------------------------------------------------------------
algorithms/brace_checker.cpp 22 22 100%
algorithms/brace_checker_test.cpp 12 12 100%
module_name/myclass.cpp 4 0 0% 5-9
module_name/myclass_test.cpp 5 5 100%
module_name2/main.cpp 4 0 0% 5-9
module_name2/test_main.cpp 5 5 100%
------------------------------------------------------------------------------
TOTAL 52 44 84%
------------------------------------------------------------------------------
------------------------------------------------------------------------------
GCC Code Coverage Report
Directory: /home/sopniews/work/priv/template_cmake_project/src
------------------------------------------------------------------------------
File Branches Taken Cover Missing
------------------------------------------------------------------------------
algorithms/brace_checker.cpp 38 28 73% 8,9,12,13,16,18,23,25,26,28
algorithms/brace_checker_test.cpp 118 31 26% 13,14,15,16,17,18,19,20
module_name/myclass.cpp 0 0 --%
module_name/myclass_test.cpp 18 9 50% 9,10
module_name2/main.cpp 0 0 --%
module_name2/test_main.cpp 18 9 50% 9,10
------------------------------------------------------------------------------
TOTAL 192 77 40%
------------------------------------------------------------------------------

 

Leave a comment