CMake:unit testing的项目结构
我想构build我的项目,包括生产源(在src
子文件夹)和testing(在test
子文件夹)。 我正在使用CMake来build立这个。 作为一个最小的例子,我有以下文件:
的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,并不重要
testing/的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)
testing/ 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)); }
几个问题:
- 这个结构是否有意义? 构build这些代码的最佳实践是什么? (我来自C#和Java,从某种意义上说它更容易)
- 我不喜欢我必须从
test/CMakeLists.txt
文件中的src
文件夹中列出所有文件的事实。 如果这是一个图书馆项目,我只会链接图书馆。 有没有办法避免从其他项目列出所有的cpp文件? -
enable_testing()
和add_test(MyTest test)
在做什么? 我没有看到任何效果。 我如何从CMake(或CTest)运行testing? - 到目前为止,我只是跑了
cmake .
在根文件夹中,但是这造成了随处可见的临时文件的混乱。 我怎样才能得到一个合理的结构编制结果?
对于问题1和2,我build议从不包含main.cpp的非testing文件(在本例中只是src / sqr.cpp和src / sqr.h)中创build一个库,然后避免列出(更重要的是重新编译)所有的来源两次。
对于问题3,这些命令会添加一个名为“MyTest”的testing,它会在没有任何参数的情况下调用可执行文件“test”。 但是,由于您已经添加了这些命令来testing/ CMakeLists.txt而不是您的顶级CMakeLists.txt,所以您只能从构build树的“test”子目录中调用testing(尝试cd test && ctest -N
)。 如果您希望testing可以从顶级构build目录运行,您需要从顶级CMakeLists.txt调用add_test
。 这也意味着你必须使用更详细的add_test
forms,因为你的testingexe文件没有在相同的CMakeLists.txt中定义
在你的情况下,因为你在根文件夹中运行cmake,所以你的构build树和你的源码树是一样的。 这被称为源内构build,并不理想,这导致了问题4。
生成构build树的首选方法是执行源代码构build,即在源代码树之外的某处创build一个目录,然后从那里执行cmake。 甚至在你的项目的根目录下创build一个“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)
testing/的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的例子,但会在test / CMakeLists.txt中使用add_test命令,并在add_subdirectory(test)之前使用enable_testing。
这样,您可以在test / CMakeLists.txt中指定testing的同时,从顶层构build目录运行testing。
结果看起来像这样(我重用了@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)
testing/的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)