This is a set of cmake utilites in order to make it easy to add unit tests to a C++ library, when using googletest, catch or doctest.
It provides a cmake function crt_registertest()
with the following features :
- Automatic discovery of the tests (outside of even inside the library source files)
- Automatic creation of an executable target for the tests, and registration with
ctest
(i.emake test
) - Automatic link the test target with the test library (providing an approriate main() function)
- Automatic inclusion of the test library include path
Tests code should be able to reside inside separate source files, as well as directly inside the library source files
The doctest documentation says rightfully:
Tests can be considered a form of documentation and should be able to reside near the production code which they test.
However, storing the test code is inside a library is often cumbersome : your tests might not be launched at all! The linker often strips the self-registration code when it is inside a library.
This project provides a solution that enables to have tests both inside the library sources, as well as inside separate source files.
For more information about the possible issues that this project attempts to solve, see:
- Catch : "issue 421 - Document How to make Catch tests in a library be found"
- Doctest: issue 21 - Tests inside a static library
- Googletest primer : important-note-for-visual-c-users
This project was tested under OSX, Windows and Linux
- googletest, catch, or doctest
- cmake
src/crt_registerstaticlibrary.cmake
provides a crt_registertest()
functions that make it possible to add tests to a library, using a simple instruction in the CMakeList.txt
of your library.
Two cases are possible:
add_library(MyLibrary STATIC lib1.cpp)
crt_registertest(
LIBRARY MyLibrary
OUTPUT_TEST_TARGET MyLibraryTest
TEST_SOURCES lib1_test.cpp
)
This will :
- Create an executable test target (MyLibraryTest) for your library.
- Register it as a cmake test (so that
ctest
ormake test
) will launch it. - Link this test target with your library
- Append the test library include path to your
TEST_SOURCES
For an example, see example_doctest_outertests:
add_library(MyLibrary OBJECT lib1.cpp lib2.cpp)
crt_registertest(
TEST_INPLACE
INPUT_OBJECT_LIBRARY MyLibrary
OUTPUT_LIBRARY_NAME MyLibrary_Static
OUTPUT_LIBRARY_TYPE STATIC
OUTPUT_TEST_TARGET MyLibraryTest
TEST_SOURCES lib3_test.cpp lib4_test.cpp
)
This will :
- First compile your library source files (lib1.cpp and lib2.cpp) as an "object" library.
- Create a static or dynamic library from these files (see
OUTPUT_LIBRARY_NAME
andOUTPUT_LIBRARY_TYPE
). Your source files will be compiled only once. - Create an executable test target (MyLibraryTest) for your library.
- Register it as a cmake test (so that
ctest
ormake test
) will launch it. - Append the test library include path to your
TEST_SOURCES
, as well as to the library sources - Make sure that all tests are run (whether they are inside the library source files or inside
TEST_SOURCES
)
For an example, see example_doctest:
The structure of your project should resemble the tree shown below:
YourProject/
├── CMakeLists.txt
├── YourLibrary/
│ ├── CMakeLists.txt
│ ├── lib1.cpp
│ └── lib2.cpp
├── catch
│ ├── catch.hpp # Only one of
├── doctest # catch
│ ├── doctest.h # doctest
├── gtest # or googletest is required
│ ├── include/gtest/gtest.h
|
└── cmake_registertest/ # copy or reference cmake_registertest as a submodule at the root of your project
└── src
├── cpp_runners
│ ├── catch_dynamic.cpp
│ ├── catch_main.cpp
│ ├── doctest_dynamic.cpp
│ └── doctest_main.cpp
├── crt_registertest.cmake
├── crt_registertest_catch.cmake
├── crt_registertest_doctest.cmake
└── crt_registertest_googletest.cmake
cmake_minimum_required(VERSION 3.0)
project(my_project)
set (crt_test_lib_location ${CMAKE_SOURCE_DIR}/doctest)
include("${CMAKE_SOURCE_DIR}/cmake_registertest/src/crt_registertest_doctest.cmake")
enable_testing()
add_subdirectory(MyLibrary)
- Inside your main
CMakeLists.txt
, set the path to the include path of your test library (catch, doctest or googletest) Depending upon your test library, include one of the 3 lines below:
set (rsl_test_lib_location ${CMAKE_SOURCE_DIR}/catch)
set (rsl_test_lib_location ${CMAKE_SOURCE_DIR}/doctest)
set (rsl_test_lib_location ${CMAKE_SOURCE_DIR}/gtest/include)
- Include the script in your main CMakeLists.txt file
After having set
rsl_test_lib_location
include the correct script.Depending upon your test library, include one of the 3 lines below:
include("${CMAKE_SOURCE_DIR}/cmake_registertest/src/crt_registertest_catch.cmake")
include("${CMAKE_SOURCE_DIR}/cmake_registertest/src/crt_registertest_googletest.cmake")
include("${CMAKE_SOURCE_DIR}/cmake_registertest/src/crt_registertest_doctest.cmake")
- enable tests for your project
enable_testing()
in the CMakeLists.txt
of your library, call crt_registertest()
See the examples