Note : there is a better alternative here: https://github.com/pthom/cmake_registertest
This is an adaption of doctest_registerlibrary for catch
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.
In the case of a static library, this means that the tests code should reside directly inside the library source files, and not inside separate source files.
Unfortunately, the self-registration of the tests does not work as desired when you link a static library : your tests might not be launched at all! This is due to the fact that the linker often strips the self-registration code when it is inside a library. For a more thorough explanation, see :
- catchorg/Catch2#421
- see also doctest/doctest#21 for the case of doctest
This project provides a solution, based on the further assumption that :
Adding tests to a library should be straightforward. Ideally, it should be possible to do it by using a one-line instruction in the library's CMakeList file.
This project was tested under OSX, Windows and Linux
- catch
- cmake
- python
src/catch_registerstaticlibrary.cmake
provides several cmake functions that make it possible to add tests to a library, using a one-liner instruction in your CMakeList.txt
file.
For example :
include("${CMAKE_SOURCE_DIR}/catch_registerstaticlibrary/src/catch_registerstaticlibrary.cmake")
add_library(MyLibrary STATIC lib1.cpp lib2.cpp)
# The line below will activate the tests for the library !
catch_registerstaticlibrary(MyLibrary MyLibraryTest)
This one-liner will :
- ensure that all tests are actually run. It will add minimal modifications to your code in order to ensure this. More details about this in the examples
- append the catch include path to your library
- create an executable test target (MyLibraryTest) for your library
- register it as a cmake test (so that
ctest
ormake test
) will launch it.
For example :
- copy catch.hpp into your project/catch folder
- copy catch_registerstaticlibrary at the root of your project, such as shown below:
YourProject/
├── CMakeLists.txt
├── YourLibrary/
│ ├── CMakeLists.txt
│ ├── lib1.cpp
│ └── lib2.cpp
├── catch
│ ├── catch.hpp
└── catch_registerstaticlibrary/
└── src/
├── catch_main.cpp
├── catch_registerstaticlibrary.cmake
└── rsl_registerstaticlibrary.py
Inside your main CMakeLists.txt
, set the path to your copy of catch.hpp.
For example:
set (rsl_test_lib_location ${CMAKE_SOURCE_DIR}/catch)
Enable tests in cmake, by adding the following line to your project's main CMakeLists.txt
file:
enable_testing()
in the CMakeLists.txt
of your library
- Include "catch_registerstaticlibrary.cmake"
- Call
catch_registerstaticlibrary(YourLibrary YourLibraryTest)
(where YourLibrary is the name of your library and YourLibraryTest is the name of the test executable that will be created)
Example :
include("${CMAKE_SOURCE_DIR}/catch_registerstaticlibrary/src/catch_registerstaticlibrary.cmake")
add_library(MyLibrary STATIC lib1.cpp lib2.cpp)
catch_registerstaticlibrary(YourLibrary YourLibraryTest)
catch_registerstaticlibrary(YourLibrary YourLibraryTest)
does different actions that can be called separately. See below for the detail of those actions.
rsl_registercppfiles(YourLibrary)
will make some small changes to your cpp files in order to ensure that tests are actually run : it will modify your cpp files by adding a dummy function catchRegister_[GUID]()
.
This modification is done only once, and can be committed. Your cpp files will not be modified unless they actually use catch (i.e they include catch.hpp
or they include a TEST_CASE
or a SCENARIO
)
`
rsl_registermainfile(YourLibrary)
will create a file rsl_registerstaticlibrary.cpp
that will call these dummy functions : this is the secret in order to make the self-registration of tests work with a static library.
This file can also be committed and will only be modified when new source files are added to the library.
See the examples for more details.
rsl_appendregistermainfiletosources(YourLibrary)
can be used in conjunction with rsl_registercppfiles()
. It will add the rsl_registerstaticlibrary.cpp
file to your library sources files.
rsl_addincludepath(YourLibrary)
will simply add the catch include path to your library.
rsl_maketesttarget(YourLibrary YourLibraryTest)
will create an executable target for your tests
rsl_registercmaketest(YourLibraryTest)
will register this exe as a test (so that make test
or ctest
will launch it)