Googletest Eclipse C++:如何同时拥有测试和生产可执行文件?

Googletest Eclipse C++ : How to have both test and production executable?

我有一个关于 Eclipse 中 Googletest 的基本问题。

我正在使用 test-runner 插件到 运行 Google 测试。 但是我需要指定一个二进制文件,它 运行 是我的单元测试(当然这是有道理的。)

问题是在我的项目中我现在有两个主要函数,一个是 运行 实际程序,另一个是

int main(int argc, char** argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

到运行 google 测试。

每次我想 运行 一个我评论另一个,这当然是愚蠢的。

但是你用什么方法来处理这种情况呢?

Googletest C++ 是一个单元测试框架。这意味着它用于测试 C++ APIs 的实现。它不适用于测试 程序.

出于实际目的,C++ API 是您在 C++ 头文件中获得的内容。这 这样一个 API 的实现可能是:

  • 只是头文件本身。 (实现完全内联)
  • 头文件加单个C++源文件
  • 头文件加一堆C++源文件

概括来说,一个C++的实现API就是一个头文件加上 0 个或多个源文件。

假设您的程序 my_prog 调用您或您的团队开发的 API 用于管理小发明。实现类似于:

gizmo.h
[gizmo_0.cpp,...gizmo_N.cpp]

其中 [...] 表示 可选 ...

也许 my_prog 依赖于您或您的团队负责的其他 API, 但我们会坚持只用一个。 my_prog 使用 gizmo API 通过:-

  • 在一些源文件中使用 #include "gizmo.h"
  • 编译 [gizmo_0.cpp,...gizmo_N.cpp] 源文件,如果有的话。
  • 链接 [gizmo_0.o,...gizmo_N.o] 目标文件,如果有的话。

(gizmo_0.obj, 等等。如果你在 Windows)

应该使用 Googletest 测试 gizmo API 的实现 确认此实现是正确的,独立于 my_prog 或依赖它来管理小玩意的任何其他程序。所以纳入 在 my_prog 的实现中 的单元测试被误导了:-

也许你的同事写了另一个程序也需要管理 gizmos 有了这个实现。也许再写一篇。这是谁写的 其他程序应该重复合并 gizmo 单元测试的过程 进入它 - 相同的?不同的? - 并有条件地制作程序 编译为小发明测试工具或现实生活中应该有的任何东西?

你怎么知道 gizmo 的实现与 my_prog 独有的功能,或某些功能的实现 my_prog 以相同方式使用的其他 API - 这样当您或某人 else 试图在另一个程序中重用它,它会中断或行为错误吗?

没有依赖于此 gizmo 实现的程序可以放置 它的单元测试。使 my_prog 有条件地编译不同的 main 函数,这样它就可以 兼作 Gizmo 库的单元测试工具类似于在 牛仔裤的裤裆可以让你的头穿过。

您应该对 gizmo 库进行单元测试的方法是编写一个 的程序 该库的测试工具,仅此而已。这个程序,比如说 gizmo_test,将 使用 gizmo API 的方式与任何其他程序使用它的方式相同,但是 仅用于测试 Gizmo 库。 gizmo_test 要做的就是执行测试 gizmo 库,通过调用它的 API.

作为第一个近似值,gizmo_test 的 GoogleTest 配方是:

写一个头文件,gizmo_test.h

#include "gizmo.h"里面

#include <gtest/gtest.h>里面

然后在里面写你的Googletest测试用例

编写如下源文件gizmo_test.cpp

#include "gizmo_test.h"

int main(int argc, char** argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

创建项目 gizmo_test - 在 Eclipse 或您使用的任何开发环境或构建系统中 - 通过以下方式构建 gizmo_test 可执行文件:

  • 编译源文件gizmo_test.cpp + [gizmo_0.cpp,...gizmo_N.cpp]
  • 链接生成的目标文件 gizmo_test.o + [gizmo_0.o,...gizmo_N.o],加上 libgtest 和您的 gizmo 库所依赖的任何其他库

您有两个个项目。一个使my_prog,一个使gizmo_test。在您的开发环境中或 构建系统,使 my_prog 的构建依赖于 gizmo_test 的构建,这样当你改变任何影响 gizmo 库和重建 my_proggizmo_test 首先重建。

这是第一个近似值。您是否注意到前一段时间我开始谈论您的 gizmo library?就是这样 你有(或应该有)。在 C++ 和编程中,API 的实现称为 .

也许您还注意到 gizmo_test 的配方中存在一些脆弱性、不便性和浪费。你有相同的一组 gizmo 源文件 [gizmo_0.cpp,...gizmo_N.cpp] 在两个项目中。因此,您可以在两个项目中以不同的方式编辑、编译和 link 它们。它们将在两个项目中以不同的方式进行编译, 这是错误的,或者相同,这是没有意义的。

当然,如果这组源文件是空的——gizmo 库就是gizmo.h——就没有这样的问题。但如果它不是空的, 有。

如您所知,在 C++ 中,我们不会通过在每个使用它的程序中构建其源文件来使用库 - 除非它是一个仅包含头文件的库。 一个库被自己构建成一个 object 库(静态的或动态的),要使用它,一个程序只包含库的 头文件和 links 对象库。

这也是程序使用您的 gizmo 库的方式。所以到最后的近似值:-

  • 制作一个项目 libgizmo 来构建 gizmo 对象库(静态或动态,如您所愿)。
  • 像上面那样制作一个项目gizmo_test,除了不是编译和linking [gizmo_0.cpp,...gizmo_N.cpp],它只是links libgizmo,然后制作这个项目 取决于 libgizmo 项目。
  • 像现在一样制作一个项目 my_prog,但不是编译和 linking [gizmo_0.cpp,...gizmo_N.cpp],只是 link libgizmo,然后制作这个项目 取决于 gizmo_test 项目。

因此,在您构建第一个使用 gizmo 库的程序时,您已经有 三个 个项目。每个使用 gizmo 库的后续程序都需要一个 更多项目,例如 my_prog 项目。

Googletest 专为测试 C++ 而设计,这就是您应该如何使用它。

现在我对你的程序一无所知,也不知道你目前是如何在你的项目中部署 Googletest 测试用例的。也许其中 没有任何 明确定义的 API 实现 这些测试用例应该执行,您可以分解到独立的库中。可能是因为您的程序非常简单 对其 "components" 进行单元测试是不适用的,您最好只编写程序的黑盒测试。更有可能是因为你到目前为止都失败了 设计一个能够进行单元测试的程序架构。如果这是您发现的问题,您需要修复它,然后以正确的方式应用 Googletest。这将是值得的 努力。

需要指出的是,单元测试不是 程序 测试,如果您负责对您的程序所依赖的任何库进行单元测试也是如此,您需要对您的程序进行黑盒测试。

确实是一个有效的问题。我相信 Mike Kinghan 的详细回复解释了您应该如何使用 google-test 但没有什么是一成不变的,最后,您可以以任何您想要的方式使用 google-test。

所以,其实我也遇到过类似的情况,所以我做的比较简单。

我修改了production文件源码,所以main函数会变成这样:

void main(void)

对此:

#ifndef TDD_ENABLED // TDD_ENABLED is defined only in the unit test project
    void main(void)
#else
    void main_app(void)
#endif

这样当你运行单元测试时,原来的'main'函数被转换为'main_app'并且你避免了与[=27=的'main'冲突] 测试。当您是 运行 原始生产代码项目时,'main_app' 函数将按原样再次命名 'main'。因此,从技术上讲,从您的生产代码的角度来看,没有任何改变。