Generating Code Coverage¶
C++¶
Background¶
GCC and LLVM have tooling built in to allow a developer to view the code coverage from their tests.
This will work for native C++ code and any code executed via Python, as the instrumentation is compiled into the binary output. Gcovr will also filter out any non-project code automatically.
C++ Specific Notes¶
The coverage target(s) do not run the tests automatically. Users must either run the test(s) or file(s) they are interested in manually for data to be produced by the tooling.
Setup¶
Enable coverage in CMake through the GUI or using
cmake /path/to/src -DCOVERAGE=ON ninja # or make
Install gcovr
pip3 install gcovr
Run C++/Python test(s) using ctest or the executable, or similar.
Producing a coverage report automatically¶
The following targets are available to make/ninja:
coverage : Builds all available coverage reports
coverage_clean : Removes all instrumented data and report data
coverage_cpp : Builds coverage information on cpp files
HTML output is written into: <build_dir>/coverage/<lang>/html
Where <lang> is either cpp or python.
Producing a coverage report manually¶
Create a folder for the html files, for example html
From your build folder generate a HTML report for the coverage as follows:
gcovr -r <src_dir> -j <n_threads> --exclude-throw-branches --html --html-details -o html/<output>.html .
Where:
-r Points to the full path of your source directory. Note: A trailing slash must be present, i.e. /my/src/ instead of /my/src
-j is the number of threads to run whilst generating, if you’re unsure pick a value like 8.
-o controls the html output directory and file name
–exclude-throw-branches Gcovr will incorrectly show compiler inserted branches as unused, despite them not appearing in the source code. This filters them out making the branch hit rate sane.
(Optional) –gcov-executable if using a manually specified compiler use this to specify the appropriate gcov tool, e.g. gcov-10 for gcc-10 or llvm-cov-11 for llvm-11
Filtering specific module(s)¶
The -f flag can be appended once or multiple times to show output from a single folder or subset of folders. This works similarly to the regex filter used in unit testing.
Examples:¶
To only include, say, the scientific interfaces, it would be the relative path of the source files:
gcovr -f qt/scientific_interfaces -j <n_threads> --exclude-throw-branches --html --html-details -o html/<output>.html .
To include only API and Kernel sources:
gcovr -f Framework/Kernel -f Framework/API -j <n_threads> --exclude-throw-branches --html --html-details -o html/<output>.html .
Additionally, folders can be excluded using the -e flag, this is useful to filter out test coverage. Tests will typically have 100% coverage so tend to add noise.
gcovr -r /path/to/src -e Framework/KernelTest -j <n_threads> --exclude-throw-branches --html --html-details -o html/<output>.html .
Python¶
Unit tests can also be run to generate coverage too, this requires us to run the test using the Coverage module.
IDE¶
(Recommended)
Your IDE may already have an option to run the test with coverage enabled if it can already run the test directly.
To setup unit tests for Pycharm see the PyCharm page.
CLI¶
(Advanced)
Install Coverage:
pip3 install coverage
Make a note of the directory or test file you’d like coverage information from. Pytest will search recursively from a given directory.
cd to build directory and run your test with coverage as follows
# Where <path> is the directory or file to run PYTHONPATH=/path/to/build/bin python3 -m coverage run -m pytest <path>
To limit coverage information to only project files add the –source flag:
# Where /path/to/src/ contains Mantid source code # Note this cannot use the home dir, i.e. ~/path/to/src PYTHONPATH=/path/to/build/bin python3 -m coverage run --source=</path/to/src/> -m pytest <path>
Example: To run coverage for the entire project
PYTHONPATH=/path/to/build/bin python3 -m coverage run --source /mantid_src -m pytest /mantid_src
Generate out a html report in the directory you ran tests from:
# This will generate htmlcov/index.html coverage html