Martin
Martin

Reputation: 171

How to make BOOST unit tests run when building a project

I'm working on a C++ project organized into libraries as follows:

├── Lib_1
│   ├──  ...
│   └──  CMakeLists.txt
├── Lib_2
│   ├──  ...
│   └──  CMakeLists.txt
│   ...
├── Lib_N
│   ├──  ...
│   └──  CMakeLists.txt
├── Main.cpp
└── CMakeLists.txt

With main executable outside of the folder structure. The main CMakeLists has the following contents:

cmake_minimum_required(VERSION 3.10)

project(MyConsoleApp VERSION 1.0)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)

add_subdirectory(Lib_1)
add_subdirectory(Lib_2)
...
add_subdirectory(Lib_N)

add_executable(${PROJECT_NAME} Main.cpp)

target_link_libraries(${PROJECT_NAME}
    Lib_1
    Lib_2
    ...
    Lib_N
)

and CMakeLists in sub-folders:

set(Lib_k_Src  # k = 1,2,...,N
    src1.h
    src1.cpp
    ...
)
add_library(Lib_k ${Lib_k_Src})

I'd like to attach a BOOST (or any other) unit test suite to each Library component, and make sure it runs every time a component is built. Or, alternatively, generate executables with test suites that can be run separately from the main exec.

So far, all of my attempts failed at integrating both Boost and CppUnit with the main executable resulting in linker error (usually LNK1104) when attaching a third party unit test library. I've created Windows environment variables for boost include and lib dirs, and tried some available examples with CMake, but these won't even configure in the CMakeGUI. The only luck I've had was with CppUnit in a separate solution without wrappers generated by CMake with a CppTestRunner at runtime through Main.cpp.

Any idea on how to approach this?

I've spent days trying to solve this, and even thought about implementing my own assert macros for testing so that they can be called from main at runtime.

My setup with Boost can be found here. Currently, I've generated a test library Symplekt_GeometryBase_Tests to Symplekt_GeometryBase as a prototype. Thanks for any helpful insight.

Upvotes: 0

Views: 1076

Answers (1)

ComicSansMS
ComicSansMS

Reputation: 54737

You're missing a number of things. Be sure to re-read Boost's extensive documentation on the different usage variants in which the unit tests library can be consumed during a build.

  • Use find_package(Boost REQUIRED) to find Boost during CMake configure. Depending on whether you use the header only version or the library version, you will in the latter case need to add unit_test_framework as the required component for the find call. You probably want to do this in your top-level CMakeLists.txt. If this fails to find Boost automatically, try setting the Boost_ROOT environment variable to the installation directory for Boost on your machine, or check out the numerous other answers here on StackOverflow for finding Boost with CMake. (Hint: If this keeps failing for no apparent reason, you probably haven't built/installed Boost correctly).
  • Have your test executable target pull in Boost as a dependency by calling target_link_libraries(mytest PUBLIC Boost::boost). Again, if you're not using the header-only setup, you will also want to link to Boost::unit_test_framework in the same manner. Get rid of all the ${BOOST_WHATEVER} variables you're currently using, you won't need any of that.
  • You will want to call enable_testing. This should ideally be done once in the root CMakeLists before including any tests.
  • Use add_test to register the test targets with CMake's test mechanism. It seems you're already doing this.

Your unit tests will now be registered with CMake's test runner and can be executed through building the respective CMake meta-targets (like RUN_TESTS) or via ctest.

You can have the tests execute automatically during the build by adding a custom build step that invokes the test runner.

Upvotes: 1

Related Questions