运行所有测试或经过某次测试后,C ++单元测试失败

时间:2014-03-27 15:24:22

标签: c++ unit-testing cmake googletest

我正在使用GoogleTest进行单元测试,今天当我添加一个新测试时,我发现它在单独运行时通过并在运行所有测试时失败。我已经阅读了一些问题和答案,但它们与C#相关联。

我使用C ++和CMake来做这件事。

我的CMakeLists.txt看起来像这样:

cmake_minimum_required(VERSION 2.8)

option(test "Build all tests." OFF)

set(EXECUTABLE_NAME proj)

project(${EXECUTABLE_NAME})

set(CMAKE_CXX_FLAGS "-g -Wall")

include_directories(src/main/cpp
                    ${Boost_INCLUDE_DIRS}
                    )

find_package(OpenCV REQUIRED core
                             imgproc
                             highgui
                             )
find_package(Boost REQUIRED COMPONENTS filesystem 
                                       system 
                                       regex 
                                       program_options
                                       )


  add_executable( ${EXECUTABLE_NAME}
# .........
                         )

  target_link_libraries(${EXECUTABLE_NAME} ${OpenCV_LIBRARIES}
                                           ${Boost_LIBRARIES}
                                           )

if (test)
  find_package(GTest REQUIRED)

  enable_testing()

  include_directories( ${GTEST_INCLUDE_DIRS} )

  add_executable(${EXECUTABLE_NAME}_test1
#  .............
            )

  add_executable(${EXECUTABLE_NAME}_test2
#  .............
            )  
  add_executable(${EXECUTABLE_NAME}_test3
#  .............
            )  
  add_executable(${EXECUTABLE_NAME}_test4
#  .............
            )

  target_link_libraries(${EXECUTABLE_NAME}_test1
                    ${OpenCV_LIBRARIES}
                    ${Boost_LIBRARIES}
                    ${GTEST_LIBRARIES}
                    gtest_main
                    pthread
                    )

  target_link_libraries(${EXECUTABLE_NAME}_test1
                    ${OpenCV_LIBRARIES}
                    ${Boost_LIBRARIES}
                    ${GTEST_LIBRARIES}
                    gtest_main
                    pthread
                    )
  target_link_libraries(${EXECUTABLE_NAME}_test2
                    ${OpenCV_LIBRARIES}
                    ${Boost_LIBRARIES}
                    ${GTEST_LIBRARIES}
                    gtest_main
                    pthread
                    )
  target_link_libraries(${EXECUTABLE_NAME}_test3
                    ${OpenCV_LIBRARIES}
                    ${Boost_LIBRARIES}
                    ${GTEST_LIBRARIES}
                    gtest_main
                    pthread
                    )
  target_link_libraries(${EXECUTABLE_NAME}_test4
                    ${OpenCV_LIBRARIES}
                    ${Boost_LIBRARIES}
                    ${GTEST_LIBRARIES}
                    gtest_main
                    pthread
                    )

  add_test(${EXECUTABLE_NAME}_test1
       ${EXECUTABLE_NAME}_test1
       )

  add_test(${EXECUTABLE_NAME}_test2
       ${EXECUTABLE_NAME}_test2
       )  
  add_test(${EXECUTABLE_NAME}_test3
       ${EXECUTABLE_NAME}_test3
       )  
  add_test(${EXECUTABLE_NAME}_test4
       ${EXECUTABLE_NAME}_test4
       )
endif()

我使用这样的测试:

#pragma once

#include <gtest/gtest.h>

#include "My.hpp"

/** Testing 
 */
TEST(qsdf, asdf)
{
 // ... initialization
 // ... test
}

我曾尝试使用TEST_F代替TEST但它崩溃了,它说没有声明qsdf(我必须承认我之前没有做过很多单元测试)。

我已经读过,其他测试可能会修改某些东西,我认为这是真的,因为我在其他一些测试后再次单独运行测试。

我的问题是:如何使用CMake在C ++中初始化每个测试(在Linux下,如果这很重要)?

1 个答案:

答案 0 :(得分:2)

这听起来像是涉及共享资源的问题(正如您所怀疑的那样)。

每个测试的初始化完全在您的测试文件中完成,没有CMake的任何额外参与等。正如您所提到的,测试通常包括初始化阶段,然后是实际测试。此外,在测试完成后包含 cleanup 步骤并不罕见。例如:

TEST(qsdf, asdf)
{
    // ... initialization
    // ... test
    // ... **cleanup**
}

通常,初始化和清理阶段只涉及分配和取消分配测试中使用的变量。但这些阶段通常是为了准备进行测试,并在之后进行清理。

如果您正在测试共享资源的代码,那么初始化阶段包括根据需要初始化这些资源; 清理阶段包括将这些资源重置回初始阶段之前的状态

当您拥有共享资源的测试时,使用测试夹具协调资源的初始化/清理会很有帮助。这是googletest中TESTTEST_F宏之间的差异 - 后者表示基于测试夹具的测试。

googletest AdvancedGuide有很多关于使用测试夹具的信息:

https://github.com/google/googletest/blob/master/googletest/docs/advanced.md#sharing-resources-between-tests-in-the-same-test-case

TEST更改为TEST_F时代码损坏的原因是因为您没有定义测试期望找到的测试夹具,这是宏的第一个参数。在googletest中,测试夹具只是一个继承自::testing::Test类的类,因此您需要执行以下操作:

#pragma once

#include <gtest/gtest.h>

#include "My.hpp"

class MyTestFixture : public ::testing::Test
{
public:
    virtual void SetUp() // This is defined in ::gtest::Test and overridden here
    {
        // This code will run before every test that uses this fixture
    }

    virtual void TearDown() // This is defined in ::gtest::Test and overridden here
    {
        // This code will run after every test that uses this fixture
    }
};

/** Testing 
 */
TEST_F(MyTestFixture, asdf)
{
    // ... initialization (after SetUp)
    // ... test
    // ... cleanup (before TearDown)
}