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_prog
,gizmo_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'。因此,从技术上讲,从您的生产代码的角度来看,没有任何改变。
我有一个关于 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_prog
,gizmo_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]
,它只是linkslibgizmo
,然后制作这个项目 取决于libgizmo
项目。 - 像现在一样制作一个项目
my_prog
,但不是编译和 linking[gizmo_0.cpp,...gizmo_N.cpp]
,只是 linklibgizmo
,然后制作这个项目 取决于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'。因此,从技术上讲,从您的生产代码的角度来看,没有任何改变。