我有一个关于Eclipse中Googletest的基本问题。
我正在使用测试运行程序插件来运行谷歌测试。但我需要指定一个二进制文件来运行我的单元测试(当然这是有意义的)
问题是,在我的项目中,我现在有两个主要功能,一个是运行实际程序,另一个是
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
运行谷歌测试。
每次我想运行一个,我都会评论另一个,这当然是愚蠢的。
但是你用什么方法来处理这种情况呢?
GoogletestC++是一个单元测试框架。这意味着它是为了测试C++API的实现。它不用于测试程序。
出于实用目的,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
实现中实现的单元测试是错误的:-
也许你的同事写了另一个程序,也需要管理小发明通过这种实现。也许你写另一个。是谁写的吗其他程序应该重复合并gizmo单元测试的过程还是一样的?不同的?-并有条件地制作程序编译成小发明测试工具还是现实生活中应该有的样子?
你怎么知道gizmo的实现不会以某种方式与my_prog
独有的功能my_prog
以相同方式使用的其他API-因此当您或某人其他人试图在另一个程序中重用它,它会崩溃或行为错误吗?
没有依赖于此gizmo实现的程序可以放置其单元测试。使my_prog
有条件地编译不同的main
函数,使其可以用作gizmo库的单元测试线束类似于在牛仔裤的胯部,让你的头穿进去。
单元测试gizmo库的方法是编写一个是测试这个库的线束,而不是其他任何东西。这个程序,比如gizmo_test
,将使用gizmo API的方式与任何其他程序使用它的方式相同,但是仅用于测试gizmo库。gizmo_test
所要做的就是执行测试通过调用小控件库的API。
作为第一个近似值,gizmo_test
的GoogleTest配方是:
编写头文件gizmo_test.h
中的#include "gizmo.h"
#include <gtest/gtest.h>
在it 中
然后在中编写你的Googletest测试用例
编写以下源文件gizmo_test.cpp
#include "gizmo_test.h"
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
在Eclipse或您使用的任何开发环境或构建系统中创建项目gizmo_test
-构建可由执行的gizmo_test
- 编译源文件
gizmo_test.cpp
+[gizmo_0.cpp,...gizmo_N.cpp]
- 链接生成的对象文件
gizmo_test.o
+[gizmo_0.o,...gizmo_N.o]
,加上libgtest
和gizmo库所依赖的任何其他库
您有两个项目。制造CCD_ 29的那个和制造gizmo_test
的那个。在您的开发环境中或构建系统,使my_prog
的构建依赖于gizmo_test
的构建,这样当您更改任何影响首先重建gizmo库和重建my_prog
、gizmo_test
。
这是第一个近似值。你有没有注意到不久前我开始谈论你的小控件库?就是这样你已经(或应该)。在C++和编程中,API的实现通常称为库。
也许你也注意到了gizmo_test
配方中的一些脆弱、不便和浪费。您有相同的gizmo源文件集CCD_ 36。因此,您可以在两个项目中以不同的方式编辑、编译和链接它们。它们将在两个项目中进行编译,或者不同,这是错误的,或者相同,这是毫无意义的。
当然,如果这组源文件是空的——gizmo库只是gizmo.h
——就没有这样的问题。但如果它不是空的,有。
正如你所知,在C++中,我们不会通过在每个使用它的程序中构建它的源文件来使用库——除非它是一个只有头的库。库本身被构建成对象库(静态或动态),为了使用它,程序只包括库的头文件并链接对象库。
程序也应该这样使用gizmo库。因此,最终近似值为:-
- 制作一个
libgizmo
项目,该项目用于构建gizmo对象库(静态或动态,视情况而定) - 如上所述制作一个项目
gizmo_test
,只是它没有编译和链接[gizmo_0.cpp,...gizmo_N.cpp]
,而是只链接libgizmo
,并制作这个项目取决于CCD_ 42项目 - 制作一个项目
my_prog
,但不要编译和链接[gizmo_0.cpp,...gizmo_N.cpp]
,只需链接libgizmo
,然后制作这个项目取决于CCD_ 46项目
因此,在构建第一个使用gizmo库的程序时,您有三个项目。使用gizmo库的每个后续程序都需要一个更多项目,如my_prog
项目。
Googletest是为测试C++库而设计的,这就是你应该如何使用它
现在我对你的程序一无所知,也不知道你目前是如何在项目中部署Googletest测试用例的。也许其中没有定义良好的API实现这些测试用例应该进行练习,您可以将其考虑到独立库中。可能是因为你的程序非常简单单元测试它的"组件"是不适用的,您最好只编写程序的黑盒测试。更有可能是因为你到目前为止失败了设计一个能够进行单元测试的程序体系结构。如果这就是你发现的,你需要修复它,然后以正确的方式应用Googletest。这将是值得的努力
如果需要指出的话,单元测试不是程序测试,因此,除了单元测试程序所依赖的任何库外,如果它们是您的责任,还需要程序的黑盒测试。
确实是一个有效的问题。我相信Mike Kinghan的详细回应解释了你应该如何使用谷歌测试,但没有什么是板上钉钉的,最终,你可以用任何你想要的方式使用谷歌测试。
因此,由于我实际上遇到了类似的情况,我所做的相当简单。
我修改了生产文件的源代码,使主要功能从此更改:
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函数会转换为mainapp,从而避免与google测试的main发生冲突。当您运行原始生产代码项目时,"main_app"函数将再次命名为"main"。因此,从技术上讲,从生产代码的角度来看,没有任何变化。