gTest接口流程测试框架部署文档.docx
《gTest接口流程测试框架部署文档.docx》由会员分享,可在线阅读,更多相关《gTest接口流程测试框架部署文档.docx(11页珍藏版)》请在冰豆网上搜索。
![gTest接口流程测试框架部署文档.docx](https://file1.bdocx.com/fileroot1/2023-2/4/53df7d08-f2ea-4bd8-8eb5-bd3339b7e252/53df7d08-f2ea-4bd8-8eb5-bd3339b7e2521.gif)
gTest接口流程测试框架部署文档
gTest测试框架的部署
一、gTest简介
1、gtest框架结构
gtest使用了xUnit的框架,xUnit的框架的公共的特点是包含了一下几个元素:
∙testcase:
测试用例集
∙test:
测试用例
∙testfixture:
构造测试用例的公共前提条件或状态
∙testsetup:
构造测试的前提条件或状态
∙testteardown:
还原到测试执行前的状态
∙assertion:
断言,用于检查
2、gtest的源代码结构
如下图
简单说一下目录结构:
msvc是针对visualstudio创建的gtest的工程文件,make文件夹下是针对linux的Makefile,xcode和codegear不用解释了。
script文件夹下是一些脚本用于产生测试用例的,test下是测试gtest框架本身的一些代码。
其中源代码包含在include、src两个文件夹中着重看一下src文件夹中的这些源文件。
gtest.cc文件实现了gtest的框架和对外接口
gtest_main.cc定义的main函数
gtest-all.cc包含了所有源文件
gtest-death-test.cc实现了死亡测试相关的内容
gtest-filepath.cc
gtest-port.cc定义了一写平台移植相关的内容
gtest-printers.cc
gtest-test-part.cc
gtest-typed-test.cc定义了参数化测试的内容
gtest-internal-inl.h是gtest内部使用的,用户不应该包含该头文件,否则会编译出错
3、gtest的主要函数介绍
1)main函数
我们看代码一般习惯从main函数开始入手,我们就先从main函数说起吧,gtest为我们提供标准的main函数,在src/gtest_main.cc文件中,内容如下。
1
2
3
4
5
6
7
8
9
10
#include
#include"gtest/gtest.h"
GTEST_API_int main(int argc,char **argv)
{
printf("Runningmain()fromgtest_main.cc\n");
testing:
:
InitGoogleTest(&argc,argv);
return RUN_ALL_TESTS();
}
这是一个非常简单的main函数,先看库文件,gtest.h库文件定义了gtest向外提供的所有API,这个库中包括两个命名空间
testing:
包含了开放给用户使用的API。
testing:
:
internal:
定义了gtest的一些内部实现。
2)InitGoogleTest函数
InitGoogleTest()函数是gtest对外提供的一个接口函数,里面封装了一个内部的实现,代码很简单
1
2
3
4
void InitGoogleTest(int *argc,char **argv)
{
internal:
:
InitGoogleTestImpl(argc,argv);
}
InitGoogleTestImpl()是定义在internal中的实现,注意gtest中很多地方使用了这样的形式,对外接口只是简单的封装,具体实现在internal中。
这样做的好处也是明显的,对外提供统一稳定的接口,即使内部实现产生大的变动时,也不会影响到建立在gtest框架上的程序的编译和执行。
InitGoogleTest()的主要功能是完成参数的解析和创建一个UnitTest的实例,关于UnitTest将在后面讲到。
并且InitGoogleTest()在一个程序中只能调用一遍,因为在internal里定义了一个全局变量来计数InitGoogleTest()运行的次数,运行InitGoogleTest()时会先检查这个变量,超过1则直接返回。
3)InitGoogleTestImpl函数
InitGoogleTestImpl()方法中定义了初始化共做主要代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
template
void InitGoogleTestImpl(int *argc,CharType**argv)
{
g_init_gtest_count++;
//Wedon'twanttoruntheinitializationcodetwice.
if (g_init_gtest_count!
=1)return;
if (*argc<=0)return;
internal:
:
g_executable_path=internal:
:
StreamableToString(argv[0]);
#ifGTEST_HAS_DEATH_TEST
g_argvs.clear();
for (int i=0;i!
=*argc;i++)
{
g_argvs.push_back(StreamableToString(argv[i]));
}
#endif //GTEST_HAS_DEATH_TEST
ParseGoogleTestFlagsOnly(argc,argv);
GetUnitTestImpl()->PostFlagParsingInit();
}
argv是传入的命令行参数,gtest支持命令行参数,InitGoogleTestImpl()中的ParseGoogleTestFlagsOnly()对参数进行了解析并设置了相应个flag并不做其他的初始化工作,而GetUnitTestImpl()->PostFlagParsingInit()通过UnitTestImpl类中的PostFlagParsingInit()方法根据相应的flag初始化gtest。
下面着重说一下UnitTest,UnitTest也是一个对外的接口类,其功能就是负责维护和执行所有的test。
他是一个singleton,只能通过GetInstance()方法获得唯一的实例,它的内部有一个指向UnitTestImpl类的指针,UnitTestImpl是定义在internal中的UnitTest的实现,UnitTestImpl将UnitTest声明为友元类,这样UnitTest就可以访问UnitTestImpl中的成员来完成功能。
二、gtest部署步骤:
1、将mvsc中的gtest工程打开,编译release或者debug都可以。
但这与后面的测试程序的某些选项相关。
此处配置为编译成debug的。
2、编译完成后在mvsc\gtest\debug下生产gtestd.lib文件讲gtest下的include文件夹和编译生产gtestd.lib,按照如下目录放置:
新建一个gtest目录,讲include文件夹拷贝到其中,然后再建一个lib文件夹。
讲gtest的lib库拷贝其中。
目录如下图所示:
3、新建一个Win32ConsoleApplication的空程序。
4、然后添加sample.cpp、test_Unit.cpp和sample.h文件。
5、编写代码:
1)编写被测程序,将下面代码复制到sample.cpp中
intFoo(inta,intb)
{
if(a==0||b==0)
{
throw"don'tdothat";
}
intc=a%b;
if(c==0)
returnb;
returnFoo(b,c);
}
2)编写被测程序头文件,将下面代码复制到sample.h头文件中
#ifndefGTEST_SAMPLES_SAMPLE1_H_
#defineGTEST_SAMPLES_SAMPLE1_H_
//Returnsn!
(thefactorialofn).Fornegativen,n!
isdefinedtobe1.
intFoo(inta,intb);
//Returnstrueiffnisaprimenumber.
#endif//GTEST_SAMPLES_SAMPLE1_H_
3)编写测程序,将下面代码复制到test_Unit.cpp头文件中
#include"sample1.h"
#include"gtest/gtest.h"
TEST(FooTest,HandleNoneZeroInput)
{
EXPECT_EQ(2,Foo(4,10));
EXPECT_EQ(6,Foo(30,18));
}
intmain(intargc,char*argv[])
{
testing:
:
InitGoogleTest(&argc,argv);
RUN_ALL_TESTS();
return0;
}
6、将整个gtest文件夹拷贝到与sample1项目名称同级的目录下,即工程.sln的上一级目录。
然后在sample中修改如下配置:
三、遇到的问题:
1、Error1errorLNK2038:
mismatchdetectedfor'_ITERATOR_DEBUG_LEVEL':
value'0'doesn'tmatchvalue'2'inbvpmeasure.obj
编译使用的gtest.lib是release的还是debug的,需要与测试程序匹配,而这个value‘0’、value'2'还是容易解决,一般就是用Release模式去链接了一个Debug编译出的lib,或者用Debug模式链接了Release编译的lib。
2、其实对于RutimeLibrary的几种选择:
Multi-threaded(/MT) Multi-threadedDebug(/MTd) Multi-threadedDLL(/MD) Multi-threadedDebugDLL(/MDd)