Search code examples
c++cmakeboost-test

Use several test files with Boost.Test and modern CMake


I am trying to use Boost.Test (v1.69.0) with modern CMake (v3.15.0) to write and build my unit tests. The main difficulty is to split my tests in several test files: in this case Boost.Test cannot find tests.

I use the Boost distribution provided by my package manager on Linux (OpenSUSE), which means I have development headers and dynamic libraries.

Most of the documentation/tutorials/examples I found about Boost.Test/CMake interaction involves old versions of CMake (v2), and you know how much the syntax and philosophy of CMake evolved between v2 and v3. So what I found was not suited for my case.

Here is a simple MWE of my situation:

project
├── CMakeLists.txt
└── tests
    ├── test_one.cpp # first test file
    ├── test_two.cpp # second test file
    └── test_unit.cpp # main test file

The main test file, which does not contain actual testing:

// tests/test_unit.cpp
#define BOOST_TEST_MODULE "Unit Test"
#define BOOST_TEST_DYN_LINK // I use dynamic libraries of Boost
#include <boost/test/unit_test.hpp>

The first test file, which contains actual testing:

// tests/test_one.cpp
#define BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>

BOOST_AUTO_TEST_SUITE(testOne)

BOOST_AUTO_TEST_CASE(testDummy) {
        BOOST_TEST(true);
}

BOOST_AUTO_TEST_SUITE_END() // testOne

The second test file is completely equivalent, so I will not show it. The CMake configuration:

# CMakeLists.txt
# cmake version
cmake_minimum_required(VERSION 3.9...3.15 FATAL_ERROR)

# project definition
project(Dummy VERSION 0.0.0 LANGUAGES CXX)

# external libraries
find_package(Boost COMPONENTS unit_test_framework REQUIRED)

# first testing library
add_library(test_one tests/test_one.cpp)

# second testing library
add_library(test_two tests/test_two.cpp)

# test executable
add_executable(test_unit tests/test_unit.cpp)
target_link_libraries(test_unit Boost::unit_test_framework test_one test_two)

# testing command
enable_testing()
add_test(test_unit test_unit)

So, I declare the two test files as libraries and I link them statically to the main test executable.

Now, I can build this MWE, but the binary test_unit fails to find tests and outputs:

Test setup error: test tree is empty

I do not understand why. I found two unsatisfactory ways to make it work:

  1. I declare the two libraries dynamic, e.g. add_library(test_two SHARED tests/test_two.cpp). But this makes little sense to me to use dynamic linking for something living in the same directory as the executable file.

  2. I include the two test files in the main test file and remove the libraries in CMakeLists.txt. But this is ugly.

Currently, I cannot use static linking for Boost.Test, as static libraries are not provided by my package manager. I tried to use header-only Boost.Test, but the problem is the same.

What should I do?


Solution

  • As pointed out in the comments, each test file does not need to be a library. I actually only need the executable:

    # test executable
    add_executable(test_unit
        tests/test_unit.cpp
        tests/test_one.cpp
        tests/test_two.cpp
    )
    target_link_libraries(test_unit Boost::unit_test_framework)
    

    On a side note, I can even factorize the #define BOOST_TEST_DYN_LINK in test files with:

    target_compile_definitions(test_unit PUBLIC BOOST_TEST_DYN_LINK)
    

    So everything works.