Используйте несколько тестовых файлов с Boost.Test и современным CMake.

Я пытаюсь использовать Boost.Test (v1.69.0) с современным CMake (v3.15.0) для написания и создания модульных тестов. Основная сложность заключается в том, чтобы разбить мои тесты на несколько тестовых файлов: в этом случае Boost.Test не может найти тесты.

Я использую дистрибутив Boost, предоставленный моим менеджером пакетов в Linux (OpenSUSE), что означает, что у меня есть заголовки для разработки и динамические библиотеки.

Большая часть документации/учебников/примеров, которые я нашел о взаимодействии Boost.Test/CMake, включает старые версии CMake (v2), и вы знаете, насколько синтаксис и философия CMake развились между v2 и v3. Итак, то, что я нашел, не подходило для моего случая.

Вот простой MWE моей ситуации:

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

Основной тестовый файл, который не содержит фактического тестирования:

// 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>

Первый тестовый файл, содержащий реальное тестирование:

// 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

Второй тестовый файл полностью эквивалентен, поэтому я его показывать не буду. Конфигурация CMake:

# 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)

Итак, я объявляю два тестовых файла библиотеками и статически связываю их с основным исполняемым файлом теста.

Теперь я могу собрать этот MWE, но двоичный файл test_unit не может найти тесты и результаты:

Test setup error: test tree is empty

Я не понимаю почему. Я нашел два неудовлетворительных способа заставить его работать:

  1. Я объявляю две библиотеки динамическими, например, add_library(test_two SHARED tests/test_two.cpp). Но для меня мало смысла использовать динамическую компоновку для чего-то, находящегося в том же каталоге, что и исполняемый файл.

  2. Я включаю два тестовых файла в основной тестовый файл и удаляю библиотеки в CMakeLists.txt. Но это некрасиво.

В настоящее время я не могу использовать статическое связывание для Boost.Test, так как статические библиотеки не предоставляются моим менеджером пакетов. Я пытался использовать Boost.Test только для заголовка, но проблема та же.

Что я должен делать?


person Neraste    schedule 03.09.2019    source источник
comment
Вам действительно нужна библиотека для каждого тестового файла?   -  person Ian A.B. King    schedule 03.09.2019
comment
Я видел это раньше, в реальном проекте. Я думал, что это... чрезмерно. Мой бедный бедный компоновщик!   -  person Mark Storer    schedule 03.09.2019
comment
IIRC, был какой-то блог о том, как это сделать ... что-то связанное с тем, как boost_test обрабатывает создание своего собственного main(). Если вы пишете все свои тесты, нигде не указывая их основной макрос, то это завершит их для вас... но если у вас есть основной, вы можете сложить N файлов cpp в один exe.   -  person Mark Storer    schedule 03.09.2019
comment
@MarkStorer это то, что #include <boost/test/unit_test.hpp> делает с различными макросами, которые вы могли определить ранее.   -  person Neraste    schedule 04.09.2019
comment
@IanA.B.K. в реальном проекте лучше иметь один тестовый файл для каждой библиотеки функций, который тестирует только эту библиотеку функций. Какой другой вариант у меня должен быть, кроме как объявить эти тестовые файлы библиотеками в CMake?   -  person Neraste    schedule 04.09.2019
comment
Согласно boost.org/ doc/libs/1_66_0/libs/test/doc/html/boost_test/, вы можете фильтровать свои тесты различными способами (время компиляции и время выполнения), нет необходимости разбивать их на этот уровень только для контроль за исполнением.   -  person Mark Storer    schedule 04.09.2019


Ответы (1)


Как указано в комментариях, каждый тестовый файл не обязательно должен быть библиотекой. На самом деле мне нужен только исполняемый файл:

# 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)

Кстати, я могу даже факторизовать #define BOOST_TEST_DYN_LINK в тестовых файлах с помощью:

target_compile_definitions(test_unit PUBLIC BOOST_TEST_DYN_LINK)

Так что все работает.

person Neraste    schedule 04.09.2019
comment
Вероятно, вам следует пометить свой ответ как решение, если это действительно решение, чтобы оно не загрязняло категорию «нерешенных». - person Ian A.B. King; 04.09.2019
comment
Я могу сделать это с завтрашнего дня… - person Neraste; 04.09.2019