CMake: структура проекта с модульными тестами
Я пытаюсь структурировать свой проект, чтобы включить источники производства (в src папку) и тесты (в test папку). Я использую CMake, чтобы построить это. В качестве минимального примера у меня есть следующие файлы:
CMakeLists.txt:
cmake_minimum_required (VERSION 2.8)
project (TEST)
add_subdirectory (src)
add_subdirectory (test)
src / CMakeLists.txt:
add_executable (demo main.cpp sqr.cpp)
src / sqr.h
#ifndef SQR_H
#define SQR_H
double sqr(double);
#endif // SQR_H
src / sqr.cpp
#include "sqr.h"
double sqr(double x) { return x*x; }
src / main.cpp-использует sqr, на самом деле нет материя
тест/CMakeLists.txt:
find_package(Boost COMPONENTS system filesystem unit_test_framework REQUIRED)
include_directories (${TEST_SOURCE_DIR}/src)
ADD_DEFINITIONS(-DBOOST_TEST_DYN_LINK)
add_executable (test test.cpp ${TEST_SOURCE_DIR}/src/sqr.cpp)
target_link_libraries(test
${Boost_FILESYSTEM_LIBRARY}
${Boost_SYSTEM_LIBRARY}
${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}
)
enable_testing()
add_test(MyTest test)
тест/испытание.cpp:
#define BOOST_TEST_MODULE SqrTests
#include <boost/test/unit_test.hpp>
#include "sqr.h"
BOOST_AUTO_TEST_CASE(FailTest)
{
BOOST_CHECK_EQUAL(5, sqr(2));
}
BOOST_AUTO_TEST_CASE(PassTest)
{
BOOST_CHECK_EQUAL(4, sqr(2));
}
несколько вопросов:
- имеет ли эта структура смысл? Каковы наилучшие практики при структурировании этого кода? (Я исхожу из C# и java, и там в некотором смысле проще)
- мне не нравится тот факт, что я должен перечислить все файлы из . Если бы это был библиотечный проект, я бы просто связал библиотека. Есть ли способ избежать перечисления всех файлов cpp из другого проекта?
- какие строки
enable_testing()иadd_test(MyTest test)делаешь? Я не видел никакого эффекта. Как я могу запустить тесты из CMake (или CTest)? - пока я просто бежал
cmake .в корневой папке, но это создало беспорядок с временными файлами везде. Как я могу получить результаты компиляции в разумной структуре?
2 ответов:
для вопросов 1 и 2 я бы рекомендовал сделать библиотеку из ваших нетестовых файлов, исключая main.cpp (в данном случае просто src/sqr.cpp и src / sqr.h), а затем вы можете избежать перечисления (и, что более важно, повторной компиляции) всех источников дважды.
для вопроса 3 эти команды добавляют тест под названием "MyTest", который вызывает ваш исполняемый" тест " без каких-либо аргументов. Однако, поскольку вы добавили эти команды в test / CMakeLists.txt, а не ваши CMakeLists верхнего уровня.txt, вы можете вызовите тест только из подкаталога "test" вашего дерева сборки (try
cd test && ctest -N). Если вы хотите, чтобы тест был запущен из вашего каталога сборки верхнего уровня, вам нужно будет вызватьadd_testиз CMakeLists верхнего уровня.формат txt. Это также означает, что вы должны использовать более подробном видеadd_testтак как ваш тест exe не определен в тех же CMakeLists.txtв вашем случае, поскольку вы запускаете cmake в корневой папке, ваше дерево сборки и исходное дерево являются одним и то же самое. Это известно как сборка в исходном коде и не является идеальным, что приводит к вопросу 4.
предпочтительный метод для создания дерева сборки-это выполнить сборку вне источника, т. е. создать каталог где-то за пределами вашего исходного дерева и выполнить cmake оттуда. Даже создание каталога "build" в корне вашего проекта и выполнение
cmake ..обеспечит чистую структуру, которая не будет мешать вашему исходному дереву.один последний пункт, чтобы избежать вызов исполняемых файлов "test" (с учетом регистра). По каким причинам, смотрите ответ.
чтобы добиться этих изменений, я бы сделал следующее:
CMakeLists.txt:
cmake_minimum_required (VERSION 2.8) project (TEST) add_subdirectory (src) add_subdirectory (test) enable_testing () add_test (NAME MyTest COMMAND Test)
src / CMakeLists.txt:add_library (Sqr sqr.cpp sqr.h) add_executable (demo main.cpp) target_link_libraries (demo Sqr)
тест/CMakeLists.txt:find_package (Boost COMPONENTS system filesystem unit_test_framework REQUIRED) include_directories (${TEST_SOURCE_DIR}/src ${Boost_INCLUDE_DIRS} ) add_definitions (-DBOOST_TEST_DYN_LINK) add_executable (Test test.cpp) target_link_libraries (Test Sqr ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} )
мне нравится пример @Fraser, но я бы использовал команду add_test в test / CMakeLists.txt и использовать enable_testing перед add_subdirectory (test).
таким образом, вы можете запускать свои тесты из каталога сборки верхнего уровня, указывая свои тесты в Test/CMakeLists.формат txt.
результат будет выглядеть так (я повторно использовать пример @Fraser):
CMakeLists.txt
cmake_minimum_required (VERSION 2.8) project (TEST) add_subdirectory (src) enable_testing () add_subdirectory (test)src / CMakeLists.txt
add_library (Sqr sqr.cpp sqr.h) add_executable (demo main.cpp) target_link_libraries (demo Sqr)тест/CMakeLists.txt
find_package (Boost COMPONENTS system filesystem unit_test_framework REQUIRED) include_directories (${TEST_SOURCE_DIR}/src ${Boost_INCLUDE_DIRS} ) add_definitions (-DBOOST_TEST_DYN_LINK) add_executable (Test test.cpp) target_link_libraries (Test Sqr ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} ) add_test (NAME MyTest COMMAND Test)
Comments