在google测试中跨多个文件分离测试用例

Separate test cases across multiple files in google test

本文关键字:文件 分离 测试用例 google 测试      更新时间:2023-10-16

我是google测试c++框架的新手。它很容易使用,但我想知道如何将案例分离到多个测试文件。最好的方法是什么?

直接包含。cpp文件是一个选项。使用标题似乎什么也做不了…

欢迎任何帮助

创建一个只包含运行测试的主文件。

// AllTests.cpp
#include "gtest/gtest.h"
int main(int argc, char **argv)
{
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

然后将测试放到其他文件中。您可以在一个文件中放入任意多的测试。为每个类或每个源文件创建一个文件可以很好地工作。

// SubtractTest.cpp
#include "subtract.h"
#include "gtest/gtest.h"
TEST(SubtractTest, SubtractTwoNumbers)
{
    EXPECT_EQ(5, subtract(6, 1));
}

这确实要求所有测试可以共享相同的main。如果你必须在那里做一些特别的事情,你必须有多个构建目标。

不寻找学分或积分。我是stackoverflow的新手,没有添加评论的声誉。@jkoendev的回答尽管在技术上是正确的,但却做出了一个不正确的陈述:"我认为另一个答案的主要遗漏点是你需要#包括测试文件。"不是这样的,你只需要把所有的CPP文件链接在一起。

例如在CMAKE

add_executable(${PROJECT_NAME} 
    ${sources}
    ${headers})

file(GLOB_RECURSE sources
    ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)

链接所有CPP文件。您不需要在主文件中包含任何测试文件。

我认为在另一个答案中主要遗漏的一点是您需要#include测试文件。

下面是我划分测试的方法:

  1. 将测试放在。h文件中,可能带有头保护,但如果你注意的话,不需要。
  2. 有一个主程序,定义如下,包括测试头
  3. 编译和链接主测试程序的Makefile。

不要在所有文件中两次使用相同的测试名称!

// main_test.cc
#include <gtest/gtest.h>
#include "test_a.h"
#include "test_b.h"
#include "test_c.h"
int main(int argc, char **argv) {
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

使用googletest中的Makefile并添加规则:

#  compiles main test program
main_test.o : main_test.cc test_a.h test_b.h test_c.h $(GTEST_HEADERS)
    $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@
# links test program
main_test : main_test.o
    $(CXX) $(LDFLAGS) -L$(GTEST_LIB_DIR) $^ -lgtest_main -lpthread -o $@

我使用命名约定按字母顺序排列测试:

// test_a.h
#include "some_class.h"
TEST(SomeClass, aName)
{
  library::SomeClass a("v", {5,4});
  EXPECT_EQ(a.name(), "v");
}
TEST(SomeClass, bSize)
{
  library::SomeClass a("v", {5,4});
  EXPECT_EQ(a.size(0), 5);
  EXPECT_EQ(a.size(1), 4);
}

然后可以使用

运行单独的测试
./main_test --gtest_filter=SomeClass.a*

我最近也遇到了同样的问题。

我将test_cases.omain.o归档到静态库(test_main.a)中,然后将它们与其他库链接到最终的可执行文件

我注意到它不能找到测试用例,如果我链接test_main.a

g++ -o test test_main.a -lgtest -lpthread -lXXX

但是,如果我单独链接对象,它就可以工作!

g++ -o test test_cases.o main.o -lgtest -lpthread -lXXX

我在这篇文章中找到了答案,为什么要从。o创建一个。a文件来进行静态链接?

在最后的链接步骤中有一个重要的区别。您所链接的任何目标文件都将包含在最终程序中。只有当库中的对象文件有助于解析其他对象文件中未定义的符号时,才会包含它们。如果它们不这样做,它们将不会被链接到最终的可执行文件中。

我怀疑这与Google Test的设计有关。

RUN_ALL_TESTS()宏动态运行测试类的所有实例,这意味着它在运行时获得测试用例。

因此,没有必要链接测试类的实例,因此链接器不会链接test_case.o

要添加到@jkoendev,您可以通过生成包含所有单元测试文件的单个文件来一次性包含所有头文件。如果您将单元测试文件隔离在test_cases目录下,您可以这样做:

// CMakeLists.txt
file(GLOB_RECURSE headers
    ${CMAKE_CURRENT_SOURCE_DIR}/test_cases/*.h)
set(testcases testcases.hpp)
file(TOUCH ${testcases})
file(WRITE ${testcases} "")
foreach(file IN LISTS headers)
    file(APPEND ${testcases} "#include "${file}"n")
endforeach()

然后将生成的文件包含在main_test.cc

// main_test.cc
#include <gtest/gtest.h>
#include "testcases.hpp"
...

当然,这将运行保持test_cases整洁和没有冲突文件的责任,以及处理可能会导致调试痛苦的自动生成的文件。

假设您有一个名为MyProject的项目。进一步假设在这个项目中,您有两个不同的文件A.cpp和B.cpp(具有相应的头文件A.hpp和B.hpp),您想要测试它们。

为了保持整洁,希望有两个单独的文件A.cc用于测试a.p p, b.c cc用于测试b.p p。

您需要设置CMakeLists.txt(如下所示),以便能够将所有这些编译成单个测试可执行文件。然后Google测试将从单个可执行文件中发现测试。

下面CMakeLists.txt代码片段中的注释将解释这一切是如何完成的:

#Create variables that reference all the files relevant to A
set(A_SOURCES A.cpp ATest.cc)
set(A_HEADERS A.hpp)
#Create variables that reference all the files relevant to B    
set(B_SOURCES B.cpp BTest.cc)
set(B_HEADERS B.hpp)
#Create the the single test executable MyProjectTests that will use
# all the files referenced from the variables above
add_executable(
  MyProjectTests ${A_SOURCES} ${A_HEADERS} ${B_SOURCES} ${B_HEADERS}
)
#Link google test libraries into that executable MyProjectTests
target_link_libraries(
  MyProjectTests
  GTest::gtest_main
)
include(GoogleTest)
#Tell gtest to look for tests in the MyProjectTests executable
gtest_discover_tests(MyProjectTests)