c++ - 在使用 CMake 构建 Windows DLL 期间运行单元测试

标签 c++ unit-testing dll cmake

我有一个用 cmake 构建的 C++ 库。该库通过单元测试进行测试,我想将其作为构建的一部分运行。我希望在库或单元测试源更改时运行测试。

我在 cmake 邮件列表上的过去帖子中找到了一些帮助:

http://www.cmake.org/pipermail/cmake/2010-January/034419.html

这种方法在单元测试程序上使用 add_custom_command(),当库是共享的或静态的时在 Linux 上工作,当库是静态的时在 Windows 上工作。问题是构建在 Windows 上共享的库。在这种情况下,测试会在初始构建中运行,但不会在库更改时运行。

下面是一个说明问题的例子:

CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
project(xyz)

SET(BUILD_SHARED_LIBS ON)

#----------- build library
if(${BUILD_SHARED_LIBS})
    add_definitions(-DXYZ_SHARED)
endif(${BUILD_SHARED_LIBS})
add_library(${PROJECT_NAME} xyz.cpp xyz.h)

#----------- build unit tests program
add_executable(${PROJECT_NAME}_unit_tests unit_tests.cpp)
target_link_libraries(${PROJECT_NAME}_unit_tests ${PROJECT_NAME})

#----------- run unit tests program after it is built
add_custom_command(TARGET ${PROJECT_NAME}_unit_tests
    POST_BUILD COMMAND ${PROJECT_NAME}_unit_tests)

xyz.h

#pragma once

#ifdef XYZ_SHARED
#ifdef _WIN32
#ifdef xyz_EXPORTS
#define XYZ_EXPORT __declspec(dllexport)
#else
#define XYZ_EXPORT __declspec(dllimport)
#endif
#else //_WIN32
#define XYZ_EXPORT
#endif //_WIN32
#else //XYZ_SHARED
#define XYZ_EXPORT
#endif //XYZ_SHARED

XYZ_EXPORT bool xyz_return_true();

xyz.cpp

#include "xyz.h"

XYZ_EXPORT bool xyz_return_true()
{
    return true;
}

单元测试.cpp

#include <iostream>
#include "xyz.h"

int main(int argc, char *argv[])
{
    using namespace std;

    cout << "running unit tests: ";

    if (xyz_return_true()) {
        //no error
        cout << "pass" << endl;
        return 0;
    }

    //error
    cout << "fail" << endl;
    return 1;
}

如果我在 Windows 上构建,然后更改 xyz.cpp 的函数以返回 false 并再次构建,则不会运行测试。在这种情况下,我该怎么做才能运行测试?

我认为没有运行测试是因为在构建时 xyz_unit_tests.exe 仅依赖于导入库 (xyz.lib)。库接口(interface)不变,导入库也不变。

我正在使用 Visual Studio 10 和 cmake 2.8.11.2。

最佳答案

您可以通过删除测试可执行文件作为库的构建后事件来触发测试重建。所以,例如:

if(WIN32 AND BUILD_SHARED_LIBS)
  #----------- trigger rebuild of tests if lib has changed
  get_target_property(TestPath ${PROJECT_NAME}_unit_tests LOCATION)
  add_custom_command(TARGET ${PROJECT_NAME}
      POST_BUILD COMMAND ${CMAKE_COMMAND} -E remove ${TestPath}
      COMMENT "Removing ${TestPath}")
endif()

您必须使用 LOCATION target 属性而不是 COMMAND 参数中的生成器表达式,因为这不会在 CMake 的依赖关系图中引入循环依赖关系。理想情况下,我们将 COMMAND 参数设置为:

COMMAND ${CMAKE_COMMAND} -E remove $<TARGET_FILE:${PROJECT_NAME}_unit_tests>

但这会导致库依赖于可执行文件,显然 target_link_libraries 调用会导致 exe 依赖于库。

可能有更好的方法让测试可执行文件过时而不是仅仅删除它;这对我来说似乎有点蛮力。但它应该有效。

关于c++ - 在使用 CMake 构建 Windows DLL 期间运行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18795501/

相关文章:

c++ - 如何用 OpenCV 同时显示深度和彩色视频图像?

unit-testing - `go test ./... -coverprofile=coverage.out` 不报告所有内容?

unit-testing - AngularJS - 测试指令链接功能,如何监视 Controller

c++ - 从 C++ dll 调用 VB 程序

c++ - DLL 中使用的全局变量

c++ - 开关盒中的多个条件?

c++ - 如何在一个类的不同实例之间共享互斥量?

c++ - C++ 中结构的构造函数

java - 单元测试循环已运行特定次数

c++ - botan.dll 中未处理的异常