Various Framework to do Unit Test in C++

Unit Test in C++

There are many frameworks to performs unit test in C++, we will present the most popular ones and show how to use them. The testing framework used here are Catch, Google Test and Boost Test

Code to test

We well test a simple factorial function using different frameworks. The code is as follow

// factorial.cpp
#include "factorial.hpp"

int Factorial( int number ) {
    return number <= 1 ? number : Factorial(number-1)*number;
}
// factorial.hpp
#ifndef FACTORIAL_HPP
#define FACTORIAL_HPP

int Factorial( int number );
#endif /* FACTORIAL_HPP */

Catch

It is a testing framework created by Phil Nash. This unit-test framework is very straightforward. It is header only and easy to setup. PS: the header only frame-work used here is Catch v1.

Setup

  • Download catch header from here.
  • Put the header files anywhere reachable from your project. you can put it in the project parent folder or in a directory in the header search path to find.

Define Test

To test this function, we have to tell Catch to provide a main() function, which is the test binary's entry point.

// tests-main.cpp
#define CATCH_CONFIG_MAIN
#include "catch.hpp"

then you can write test using the TEST_CASE macro. it takes a text explaining what the test does. Then you can write test in form of assertions. Catch provides various macros to test assertion, such as REQUIRE, CHECK, REQUIRE_FALSE, CHECK_FALSE.

// tests-factorial.cpp
#include "catch.hpp"
#include "factorial.cpp"

TEST_CASE( "Factorials for zero", "[factorial]" ) {
    REQUIRE( Factorial(0) == 1 );
}

TEST_CASE( "Factorials for positive numbers", "[factorial]" ) {
    REQUIRE( Factorial(1) == 1 );
    REQUIRE( Factorial(2) == 2 );
    REQUIRE( Factorial(3) == 6 );
    REQUIRE( Factorial(10) == 3628800 );
}

Running Test

To run the tests, first we compile catch-tests-main.cpp to provide us with the compiled catch header file and with the entry point.

g++ -std=c++17 -stdlib=libc++  test/catch-tests-main.cpp -o tests-main.o -c

then we run the tests with:

g++ -std=c++17 -stdlib=libc++  tests-main.o test/catch-tests-factorial.cpp -o tests && ./tests

when executing the file, we get the following output:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tests is a Catch v2.13.6 host application.
Run with -? for options

-------------------------------------------------------------------------------
Factorials for zero
-------------------------------------------------------------------------------
tests-factorial.cpp:5
...............................................................................

tests-factorial.cpp:6: FAILED:
  REQUIRE( Factorial(0) == 1 )
with expansion:
  0 == 1

===============================================================================
test cases: 2 | 1 passed | 1 failed
assertions: 5 | 4 passed | 1 failed

it tells us that TEST_CASE Factorials for zero failed and that the reason is the assertion REQUIRE( Factorial(0) == 1 ) to learn more, see here

Google Test

Google Test is Google's C++ Testing and Mocking framework. it is a production grade framework, very fast with rich set of assertions. It also provides value and type parameterized tests, XML test report and more.

setup

Google Test is not a header-only library, it must be compiled into a set of libraries and linked to the project test.

  1. clone GoogleTest repository

  2. Create a CMakeLists.txt in which you specify the program you want to test and the path to googletest installation and path to the tests folder. see example.

  3. In the test folder, create the test code and a CMakeLists.txt file in which you specify the Source file you want to test and you link it with gtest library.

  4. you run the cmake command.

cmake --build build --config Debug --target FactorialTests -j 10 --

In vscode, you can click on build as shown bellow build. make sure Cmake and CMake Tools extensions are installed

  1. Execute the test by running the generated file in the build directory. In our case FactorialTests
./build/test/FactorialTests

In vscode, you can click on the play button as shown bellow. The test name is also displayed. run_test

Writing Tests

we will test the same factorial function. the implementation is in Factorial.cpp, the header is in [Factorial.hpp] and the test is in test/FactorialTests

Define an Entry Point

Google Test will supply as main() function when we link gtest_main to the project unit-test. this linking is done in the CMakeLists.txt file using target_link_libraries cmake command.

Writing Test Cases

To create a test, we import the gtest/gtest.h header and we use the TEST macro to group our tests. TEST macro takes the test_case_name and the test_name as parameter. Google Test also provide other macros like TEST_F to access objects and subroutines, and TEST_P to write tests with parameters. GoogleTest provides many assertion macros that we can use, like ASSERT_TRUE, ASSERT_FALSE, ASSERT_EQ, ASSERT_LT, ASSERT_THROM, etc.

Test Output

After building and running the factorial tests, we get the following output

Running main() from /Users/ymektoubi/Documents/project/practice/cpp/googletest/googletest/src/gtest_main.cc
[==========] Running 2 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 2 tests from FactorialTests
[ RUN      ] FactorialTests.HandlesZeroInput
/Users/ymektoubi/Documents/project/practice/cpp/Unit-Test-in-Cpp/test/FactorialTests.cpp:23: Failure
Expected equality of these values:
  Factorial(getX())
    Which is: 0
  1
[  FAILED  ] FactorialTests.HandlesZeroInput (0 ms)
[ RUN      ] FactorialTests.HandlesPositiveInput
[       OK ] FactorialTests.HandlesPositiveInput (0 ms)
[----------] 2 tests from FactorialTests (0 ms total)

[----------] Global test environment tear-down
[==========] 2 tests from 1 test suite ran. (0 ms total)
[  PASSED  ] 1 test.
[  FAILED  ] 1 test, listed below:
[  FAILED  ] FactorialTests.HandlesZeroInput

 1 FAILED TEST

it tells us the total number to test cases, the number of failed tests, the number of succeeded test and the failed assertion.

Boost Test

Boost Test is a unit-testing framework that is part of the Boost C++ libraries. Boost Test supports three different usage variants

  • a header-only variant like catch use this to avoid compilation of standalone library. you only need to include one header and define the BOOST_TEST_MODULE at the start of the file as follow:
#define BOOST_TEST_MODULE test module name
#include <boost/test/included/unit_test.hpp>

compile the test and run it.

$ g++ test/boost-header-test-factorial.cpp -o boost-header-test-factorial.o
$ ./boost-header-test-factorial.o
  • a static library variant like Google Test To use it, you need two steps:
  1. include the following line in all translation units in the test module
#include <boost/test/unit_test.hpp>

and one and only one translation unit should include the following lines:

#define BOOST_TEST_MODULE test module name
#include <boost/test/unit_test.hpp>
  1. link with the Unit Test Framework static library
$ g++ test/boost-static-tests-factorial.cpp /usr/local/lib/libboost_unit_test_framework.a -o boost-static-tests-factorial.o
$ ./boost-static-tests-factorial.o
  • a shared library which is linked at runtime. In the project with large number of test modules the static library variant of the Unit Test Framework may cause you to waste a lot of disk space. The solution is to link test module dynamically with the Unit Test Framework built as a shared library. to do that
  1. add the following lines to all translation units in a test module:
#define BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>

and one and only one translation unit should include the following lines:

#define BOOST_TEST_MODULE test module name
#define BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>
  1. link with the Unit Test Framework shared library
$ g++ -std=c++17 -stdlib=libc++ tests-factorial_boost_shared.cpp /usr/local/lib/libboost_unit_test_framework.so -o tests-factorial_boost_shared.o

PS: to use boost test with static or shared library, you have to build the unit test framework.

cd $boost_path
> ./bootstrap.sh
> ./b2 --with-test --prefix=$boost_installation_prefix install

References

Similar Resources

End to end test framework designed for Juce applications

JUCE End to End test framework What is it? This package provides a mechanism to end-to-end test a JUCE application Prerequisites CMake. Must be 3.18 o

Aug 8, 2022

Handy C++ test framework

C++ Voyager Test Framework Voyager is a simple and handy C++ Unit Test framework. It is designed to be beautiful and expressive both. Try it to feel i

Mar 16, 2022

A micro unit-testing library for C/C++

µ-test A micro unit testing framework for C/C++ to get you up and running with unit-testing ASAP (even without libc). Usage Simply include the C and h

Dec 8, 2021

📝 One of the difficult unit tester for ft_containers project

📝 One of the difficult unit tester for ft_containers project

ft_containers-unit-test About ft containers unit test is a complete testing for project of school 21/ecole 42 and allowing you test your containers: V

Aug 7, 2022

C unit tests with a small header-only library.

C unit tests with a small header-only library.

C unit tests Minimalistic unit tests in C. Uses the __attribute__((constructor)) which, as far as I know, is supported by GCC and clang. So this proba

May 10, 2022

PlatformIO + BL602 Bouffalo Arduino Core Test

 PlatformIO + BL602 Bouffalo Arduino Core Test

PlatformIO + BL602 Bouffalo Arduino Core Test Description Uses A custom extension of the PlatformIO SiFive Platform (https://github.com/maxgerhardt/pl

May 31, 2022

A test showing a flipped bit in a file encrypted on two different machines

ChaCha ASM Test I have observed that the ChaCha cipher may have very rarely divergent code paths for AVX vs. SSE. I have seen this in earlier CryptoPP

Dec 6, 2021

A tool to test if a shared library is dlopen'ble

A tool to test if a shared library is dlopen'ble

Oct 17, 2021

An area to test reading in ATLAS xAOD format and writing out to Parquet

xaod_to_parquet An area to test reading in ATLAS xAOD format and writing out to Parquet Getting the Code Clone the repository with the --recursive fla

Nov 19, 2021
A modern, C++-native, header-only, test framework for unit-tests, TDD and BDD - using C++11, C++14, C++17 and later (or C++03 on the Catch1.x branch)
A modern, C++-native, header-only, test framework for unit-tests, TDD and BDD - using C++11, C++14, C++17 and later (or C++03 on the Catch1.x branch)

Catch2 v3 is being developed! You are on the devel branch, where the next major version, v3, of Catch2 is being developed. As it is a significant rewo

Aug 16, 2022
Upp11 - C++11 lightweight single header unit test framework

upp11 Lightweight C++11 single header unit test framework To use framework: Copy upp11.h in you project dir. Create unit test source files or modify e

Apr 4, 2019
TestFrame - This is a test framework that uses Raylib and ImGui together to help test and develop concepts
TestFrame - This is a test framework that uses Raylib and ImGui together to help test and develop concepts

This is a test framework that uses Raylib and ImGui together to help test and develop concepts. It is made using C++ because it uses classes for windows and views.

May 13, 2022
The C Unit Testing Library on GitHub is a library designed for easy unit testing in C

The C Unit Testing Library on GitHub is a library designed for easy unit testing in C. It was written by Brennan Hurst for the purpose of providing a J-Unit-like testing framework within C for personal projects.

Oct 11, 2021
A dynamic mock tool for C/C++ unit test on Linux&MacOS X86_64

lmock 接口 替换一个函数,修改机器指令,用新函数替换旧函数,支持全局函数(包括第三方和系统函数)、成员函数(包括静态和虚函数)

Jul 28, 2022
A modern, C++11-native, single-file header-only, tiny framework for unit-tests, TDD and BDD (includes C++98 variant)

lest – lest errors escape testing This tiny C++11 test framework is based on ideas and examples by Kevlin Henney [1,2] and on ideas found in the CATCH

Aug 5, 2022
UT: C++20 μ(micro)/Unit Testing Framework
UT: C++20 μ(micro)/Unit Testing Framework

"If you liked it then you "should have put a"_test on it", Beyonce rule UT / μt | Motivation | Quick Start | Overview | Tutorial | Examples | User Gui

Aug 7, 2022
A complete unit testing framework in a header

liblittletest A complete unit testing framework in a header liblittletest is an easy to use all-in-an-header testing framework; all you have to do in

Nov 11, 2021
Modern c++17 unit testing framework on Microsoft Windows, Apple macOS, Linux, iOS and android.
Modern c++17 unit testing framework on Microsoft Windows, Apple macOS, Linux, iOS and android.

tunit Modern c++17 unit testing framework on Windows, macOS, Linux, iOS and android. Continuous Integration build status Operating system Status Windo

Apr 5, 2022
Kernel-mode C++ unit testing framework in BDD-style

There is a lack of unit testing frameworks that work in OS kernel. This library closes that gap and is targeted for windows driver developers.

Jun 11, 2022