C++ CMake:带有单元测试的项目结构

C++ CMake:带有单元测试的项目结构,c++,unit-testing,boost,cmake,boost-test,C++,Unit Testing,Boost,Cmake,Boost Test,我正在尝试构建我的项目,以包括生产源(在src子文件夹中)和测试(在test子文件夹中)。我正在使用CMake来构建这个。作为一个简单的例子,我有以下文件: CMakeLists.txt: cmake_minimum_required (VERSION 2.8) project (TEST) add_subdirectory (src) add_subdirectory (test) add_executable (demo main.cpp sqr.cpp) find_pack

我正在尝试构建我的项目,以包括生产源(在
src
子文件夹中)和测试(在
test
子文件夹中)。我正在使用CMake来构建这个。作为一个简单的例子,我有以下文件:

CMakeLists.txt:

cmake_minimum_required (VERSION 2.8) 
project (TEST) 

add_subdirectory (src) 
add_subdirectory (test) 
add_executable (demo main.cpp sqr.cpp) 
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)
src/CMakeLists.txt:

cmake_minimum_required (VERSION 2.8) 
project (TEST) 

add_subdirectory (src) 
add_subdirectory (test) 
add_executable (demo main.cpp sqr.cpp) 
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)
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,这并不重要

test/CMakeLists.txt:

cmake_minimum_required (VERSION 2.8) 
project (TEST) 

add_subdirectory (src) 
add_subdirectory (test) 
add_executable (demo main.cpp sqr.cpp) 
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)
test/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));
}
#定义升压测试模块SqrTests
#包括
#包括“sqr.h”
增压自动测试案例(失败测试)
{
BOOST_CHECK_EQUAL(5,sqr(2));
}
增压自动测试用例(通过测试)
{
BOOST_CHECK_EQUAL(4,sqr(2));
}
有几个问题:

  • 这种结构有意义吗?构建此代码时的最佳实践是什么?(我来自C#和java,从某种意义上说,在那里更容易)
  • 我不喜欢在
    test/CMakeLists.txt
    文件中列出
    src
    文件夹中的所有文件。如果这是一个图书馆项目,我只会链接图书馆。有没有办法避免列出其他项目中的所有cpp文件
  • enable_testing()
    add_test(MyTest测试)
    行在做什么?我没有看到任何效果。如何从CMake(或CTest)运行测试
  • 到目前为止,我只是在根文件夹中运行了
    cmake.
    ,但这造成了到处都是临时文件的混乱。如何以合理的结构获得编译结果

  • 对于问题1和问题2,我建议从不包括main.cpp的非测试文件中创建一个库(在本例中仅为src/sqr.cpp和src/sqr.h),然后可以避免两次列出(更重要的是重新编译)所有源代码

    对于问题3,这些命令添加了一个名为“MyTest”的测试,该测试在没有任何参数的情况下调用可执行文件“test”。但是,由于已将这些命令添加到test/CMakeLists.txt而不是顶级CMakeLists.txt,因此只能从构建树的“test”子目录中调用测试(try
    cd test&&ctest-N
    )。如果希望测试可以从顶级构建目录运行,则需要从顶级CMakeLists.txt调用
    add\u test
    。这也意味着您必须使用更详细的形式,因为您的测试exe不是在同一个CMakeLists.txt中定义的

    cmake_minimum_required (VERSION 2.8)
    project (TEST)
    add_subdirectory (src)
    
    enable_testing ()
    add_subdirectory (test)
    
    add_library (Sqr sqr.cpp sqr.h)
    add_executable (demo main.cpp)
    target_link_libraries (demo Sqr)
    
    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)
    
    在您的情况下,由于您在根文件夹中运行cmake,因此构建树和源代码树是一个相同的树。这被称为源代码内构建,并不理想,这导致了问题4

    生成生成生成树的首选方法是进行源代码外生成,即在源代码树之外的某个位置创建一个目录,然后从那里执行cmake。即使在项目的根目录中创建一个“build”目录并执行
    cmake..
    也会提供一个干净的结构,不会干扰源代码树

    最后一点是避免调用可执行文件“test”(区分大小写)。有关原因,请参见

    要实现这些更改,我将执行以下操作:

    CMakeLists.txt:

    cmake_minimum_required (VERSION 2.8) 
    project (TEST) 
    
    add_subdirectory (src) 
    add_subdirectory (test) 
    
    add_executable (demo main.cpp sqr.cpp) 
    
    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)
    
    cmake_最低要求(2.8版)
    项目(测试)
    添加子目录(src)
    添加_子目录(测试)
    启用_测试()
    添加测试(名称MyTest命令test)
    

    src/CMakeLists.txt:

    cmake_minimum_required (VERSION 2.8) 
    project (TEST) 
    
    add_subdirectory (src) 
    add_subdirectory (test) 
    
    add_executable (demo main.cpp sqr.cpp) 
    
    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)
    
    add_库(Sqr Sqr.cpp Sqr.h)
    添加可执行文件(demo main.cpp)
    目标链接库(演示Sqr)
    

    test/CMakeLists.txt:

    cmake_minimum_required (VERSION 2.8) 
    project (TEST) 
    
    add_subdirectory (src) 
    add_subdirectory (test) 
    
    add_executable (demo main.cpp sqr.cpp) 
    
    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)
    
    find_包(需要Boost组件系统文件系统单元测试框架)
    包括目录(${TEST\u SOURCE\u DIR}/src)
    ${Boost\u INCLUDE\u DIRS}
    )
    添加定义(-DBOOST\u TEST\u DYN\u LINK)
    添加可执行文件(Test.cpp)
    目标链接库(测试
    Sqr
    ${Boost_文件系统_库}
    ${Boost\u SYSTEM\u LIBRARY}
    ${Boost\u UNIT\u TEST\u FRAMEWORK\u LIBRARY}
    )
    
    我喜欢@Fraser的示例,但会在test/CMakeLists.txt中使用add_test命令,并在add_子目录(test)之前使用enable_testing

    这样,您可以在test/CMakeLists.txt中指定测试的同时,从顶级生成目录运行测试

    结果如下所示(我重用了@Fraser的示例):

    CMakeLists.txt

    cmake_minimum_required (VERSION 2.8)
    project (TEST)
    add_subdirectory (src)
    
    enable_testing ()
    add_subdirectory (test)
    
    add_library (Sqr sqr.cpp sqr.h)
    add_executable (demo main.cpp)
    target_link_libraries (demo Sqr)
    
    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)
    
    src/CMakeLists.txt

    cmake_minimum_required (VERSION 2.8)
    project (TEST)
    add_subdirectory (src)
    
    enable_testing ()
    add_subdirectory (test)
    
    add_library (Sqr sqr.cpp sqr.h)
    add_executable (demo main.cpp)
    target_link_libraries (demo Sqr)
    
    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)
    
    test/CMakeLists.txt

    cmake_minimum_required (VERSION 2.8)
    project (TEST)
    add_subdirectory (src)
    
    enable_testing ()
    add_subdirectory (test)
    
    add_library (Sqr sqr.cpp sqr.h)
    add_executable (demo main.cpp)
    target_link_libraries (demo Sqr)
    
    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)
    

    我认为自己是CKED新手,所以我不知道什么是公认的最佳实践,但是FWWI我会制作一个“SQR”库,主库和测试都依赖于这个库。(*或其道德等价物)我刚刚注意到,您也相应地将.h文件添加到了CMakeLists.txt文件中。需要吗?如果我不使用它们会发生什么?@Grzenio这只是一个方便的功能-它们作为目标的一部分出现在IDE中,就像MSVC一样,但是这没有效果。TEST\u SOURCE\u DIR设置在哪里?它是由CMake在调用
    项目(TEST)时自动设置的
    -请参见>它们作为目标的一部分出现在IDE中,就像MSVC一样---MSVC不支持将带有标题的目录标记为“包含目录”?谢谢,我没有通过
    ctest-N
    显示任何测试,直到您在添加子目录之前收到关于启用测试的提示。@alaferg:否则它们将在build dir中的test子目录中结束。我希望CMake具有类似于该结构的东西。