首页 文章

CMake:具有单元测试的项目结构

提问于
浏览
101

我正在尝试构建我的项目以包含 生产环境 源(在 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)

测试/ 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,从某种意义上来说它更容易)

  • 我不喜欢我必须列出 test/CMakeLists.txt 文件中 src 文件夹中的所有文件 . 如果这是一个图书馆项目,我只想链接图书馆 . 有没有办法避免列出其他项目中的所有cpp文件?

  • enable_testing()add_test(MyTest test) 在做什么?我没有看到任何影响 . 如何从CMake(或CTest)运行测试?

  • 到目前为止,我刚刚在根文件夹中运行了 cmake . ,但这造成了各地临时文件的混乱 . 如何以合理的结构获得编译结果?

2 回答

  • 97

    我喜欢@Fraser的例子,但是会在test / CMakeLists.txt中使用add_test命令,并在add_subdirectory(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)
    

    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)
    
  • 38

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

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

    在您的情况下,由于您在根文件夹中运行cmake,因此您的构建树和源树是同一个 . 这被称为源内构建,并不理想,这导致问题4 .

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

    最后一点是避免调用可执行文件"test"(区分大小写) . 出于原因,请参阅this answer .

    为了实现这些变化,我将执行以下操作:

    的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}
                           )
    

相关问题