GTest使用手册文档格式.docx
- 文档编号:21490961
- 上传时间:2023-01-30
- 格式:DOCX
- 页数:29
- 大小:33.82KB
GTest使用手册文档格式.docx
《GTest使用手册文档格式.docx》由会员分享,可在线阅读,更多相关《GTest使用手册文档格式.docx(29页珍藏版)》请在冰豆网上搜索。
{if(a==0||b==0)
{throw"
don'
tdothat"
;
}intc=a%b;
if(c==0)returnb;
returnFoo(b,c);
}
没错,上面的函数是用来求最大公约数的。
下面我们就来编写一个简单的测试案例。
#include<
gtest/>
TEST(FooTest,HandleNoneZeroInput)
{
EXPECT_EQ(2,Foo(4,10));
EXPECT_EQ(6,Foo(30,18));
上面可以看到,编写一个测试案例是多么的简单。
我们使用了TEST这个宏,它有两个参数,官方的对这两个参数的解释为:
[TestCaseName,TestName],而我对这两个参数的定义是:
[TestSuiteName,TestCaseName],在下一篇我们再来看为什么这样定义。
对检查点的检查,我们上面使用到了EXPECT_EQ这个宏,这个宏用来比较两个数字是否相等。
Google还包装了一系列EXPECT_*和ASSERT_*的宏,而EXPECT系列和ASSERT系列的区别是:
1.EXPECT_*失败时,案例继续往下执行。
2.ASSERT_*失败时,直接在当前函数中返回,当前函数中ASSERT_*后面的语句将不会执行。
在下一篇,我们再来具体讨论这些断言宏。
为了让我们的案例运行起来,我们还需要在main函数中添加如下代码:
int_tmain(intargc,_TCHAR*argv[])
testing:
:
InitGoogleTest(&
argc,argv);
returnRUN_ALL_TESTS();
“testing:
”:
gtest的测试案例允许接收一系列的命令行参数,因此,我们将命令行参数传递给gtest,进行一些初始化操作。
gtest的命令行参数非常丰富,在后面我们也会详细了解到。
“RUN_ALL_TESTS()”:
运行所有测试案例
OK,一切就绪了,我们直接运行案例试试(一片绿色,非常爽):
5、总结
本篇内容确实是非常的初级,目的是让从来没有接触过gtest的同学了解gtest最基本的使用。
gtest还有很多更高级的使用方法,我们将会在后面讨论。
总结本篇的内容的话:
1.使用VS编译文件
2.设置测试工程的属性(头文件,lib文件,/MT参数(和编译gtest时使用一样的参数就行了))
3.使用TEST宏开始一个测试案例,使用EXPECT_*,ASSER_*系列设置检查点。
4.在Main函数中初始化环境,再使用RUN_ALL_TEST()宏运行测试案例。
优点:
1.我们的测试案例本身就是一个exe工程,编译之后可以直接运行,非常的方便。
2.编写测试案例变的非常简单(使用一些简单的宏如TEST),让我们将更多精力花在案例的设计和编写上。
3.提供了强大丰富的断言的宏,用于对各种不同检查点的检查。
4.提高了丰富的命令行参数对案例运行进行一系列的设置。
二、断言
这篇文章主要总结gtest中的所有断言相关的宏。
gtest中,断言的宏可以理解为分为两类,一类是ASSERT系列,一类是EXPECT系列。
一个直观的解释就是:
1.ASSERT_*系列的断言,当检查点失败时,退出当前函数(注意:
并非退出当前案例)。
2.EXPECT_*系列的断言,当检查点失败时,继续往下执行。
2、示例
3、
4、
5、
6、
.
...
Google人说了,他们只提供<
=5个参数的,如果需要测试更多的参数,直接告诉他们。
下面看看这个东西怎么用。
boolMutuallyPrime(intm,intn)
{returnFoo(m,n)>
1;
TEST(PredicateAssertionTest,Demo)
{intm=5,n=6;
EXPECT_PRED2(MutuallyPrime,m,n);
当失败时,返回错误信息:
error:
MutuallyPrime(m,n)evaluatestofalse,where
mevaluatesto5
nevaluatesto6
如果对这样的输出不满意的话,还可以自定义输出格式,通过如下:
Fatalassertion
Nonfatalassertion
Verifies
ASSERT_PRED_FORMAT1(pred_format1,val1);
`
EXPECT_PRED_FORMAT1(pred_format1,val1);
pred_format1(val1)issuccessful
ASSERT_PRED_FORMAT2(pred_format2,val1,val2);
EXPECT_PRED_FORMAT2(pred_format2,val1,val2);
pred_format2(val1,val2)issuccessful
用法示例:
testing:
AssertionResultAssertFoo(constchar*m_expr,constchar*n_expr,constchar*k_expr,intm,intn,intk){if(Foo(m,n)==k)returntesting:
AssertionSuccess();
Messagemsg;
msg<
<
m_expr<
"
和"
<
n_expr<
的最大公约数应该是:
"
Foo(m,n)<
而不是:
k_expr;
returntesting:
AssertionFailure(msg);
TEST(AssertFooTest,HandleFail)
EXPECT_PRED_FORMAT3(AssertFoo,3,6,2);
失败时,输出信息:
3和6的最大公约数应该是:
3而不是:
2
是不是更温馨呢,呵呵。
7、浮点型检查
ASSERT_FLOAT_EQ(expected,actual);
EXPECT_FLOAT_EQ(expected,actual);
thetwofloatvaluesarealmostequal
ASSERT_DOUBLE_EQ(expected,actual);
EXPECT_DOUBLE_EQ(expected,actual);
thetwodoublevaluesarealmostequal
对相近的两个数比较:
ASSERT_NEAR(val1,val2,abs_error);
EXPECT_NEAR(val1,val2,abs_error);
thedifferencebetweenval1andval2doesn'
texceedthegivenabsoluteerror
同时,还可以使用:
EXPECT_PRED_FORMAT2(testing:
FloatLE,val1,val2);
DoubleLE,val1,val2);
8、WindowsHRESULTassertions
ASSERT_HRESULT_SUCCEEDED(expression);
EXPECT_HRESULT_SUCCEEDED(expression);
expressionisasuccessHRESULT
ASSERT_HRESULT_FAILED(expression);
EXPECT_HRESULT_FAILED(expression);
expressionisafailureHRESULT
例如:
CComPtrshell;
ASSERT_HRESULT_SUCCEEDED(L"
));
CComVariantempty;
ASSERT_HRESULT_SUCCEEDED(shell->
ShellExecute(CComBSTR(url),empty,empty,empty,empty));
9、类型检查
类型检查失败时,直接导致代码编不过,难得用处就在这?
看下面的例子:
template<
typenameT>
classFooType{public:
voidBar(){testing:
StaticAssertTypeEq<
int,T>
();
}
};
TEST(TypeAssertionTest,Demo)
FooType<
bool>
fooType;
();
10、总结
本篇将常用的断言都介绍了一遍,内容比较多,有些还是很有用的。
要真的到写案例的时候,也行只是一两种是最常用的,现在时知道有这么多种选择,以后才方便查询。
三、事件机制
gtest提供了多种事件机制,非常方便我们在案例之前或之后做一些操作。
总结一下gtest的事件一共有3种:
1.全局的,所有案例执行前后。
2.TestSuite级别的,在某一批案例中第一个案例前,最后一个案例执行后。
3.TestCase级别的,每个TestCase前后。
2、全局事件
要实现全局事件,必须写一个类,继承testing:
Environment类,实现里面的SetUp和TearDown方法。
1.SetUp()方法在所有案例执行前执行
2.TearDown()方法在所有案例执行后执行
classFooEnvironment:
publictesting:
Environment
{public:
virtualvoidSetUp()
{
std:
cout<
FooFooEnvironmentSetUP"
endl;
}virtualvoidTearDown()
FooFooEnvironmentTearDown"
当然,这样还不够,我们还需要告诉gtest添加这个全局事件,我们需要在main函数中通过testing:
AddGlobalTestEnvironment方法将事件挂进来,也就是说,我们可以写很多个这样的类,然后将他们的事件都挂上去。
AddGlobalTestEnvironment(newFooEnvironment);
3、TestSuite事件
我们需要写一个类,继承testing:
Test,然后实现两个静态方法
1.SetUpTestCase()方法在第一个TestCase之前执行
()方法在最后一个TestCase之后执行
classFooTest:
Test{protected:
staticvoidSetUpTestCase(){
shared_resource_=new;
}staticvoidTearDownTestCase(){
deleteshared_resource_;
shared_resource_=NULL;
}staticT*shared_resource_;
在编写测试案例时,我们需要使用TEST_F这个宏,第一个参数必须是我们上面类的名字,代表一个TestSuite。
TEST_F(FooTest,Test1)
{SetUp()方法在每个TestCase之前执行
2.TearDown()方法在每个TestCase之后执行
classFooCalcTest:
publictesting:
Test
{protected:
FooCalcm_foo;
TEST_F(FooCalcTest,HandleNoneZeroInput)
EXPECT_EQ(4,(12,16));
TEST_F(FooCalcTest,HandleNoneZeroInput_Error)
EXPECT_EQ(5,(12,16));
4、总结
gtest提供的这三种事件机制还是非常的简单和灵活的。
同时,通过继承Test类,使用TEST_F宏,我们可以在案例之间共享一些通用方法,共享资源。
使得我们的案例更加的简洁,清晰。
四、参数化
在设计测试案例时,经常需要考虑给被测函数传入不同的值的情况。
我们之前的做法通常是写一个通用方法,然后编写在测试案例调用它。
即使使用了通用方法,这样的工作也是有很多重复性的,程序员都懒,都希望能够少写代码,多复用代码。
Google的程序员也一样,他们考虑到了这个问题,并且提供了一个灵活的参数化测试的方案。
2、旧的方案
为了对比,我还是把旧的方案提一下。
首先我先把被测函数IsPrime帖过来(在gtest的中),这个函数是用来判断传入的数值是否为质数的。
if(n%i==0)returnfalse;
}returntrue;
假如我要编写判断结果为True的测试案例,我需要传入一系列数值让函数IsPrime去判断是否为True(当然,即使传入再多值也无法确保函数正确,呵呵),因此我需要这样编写如下的测试案例:
TEST(IsPrimeTest,HandleTrueReturn)
EXPECT_TRUE(IsPrime(3));
EXPECT_TRUE(IsPrime(5));
EXPECT_TRUE(IsPrime(11));
EXPECT_TRUE(IsPrime(23));
EXPECT_TRUE(IsPrime(17));
我们注意到,在这个测试案例中,我至少复制粘贴了4次,假如参数有50个,100个,怎么办?
同时,上面的写法产生的是1个测试案例,里面有5个检查点,假如我要把5个检查变成5个单独的案例,将会更加累人。
接下来,就来看看gtest是如何为我们解决这些问题的。
3、使用参数化后的方案
1.告诉gtest你的参数类型是什么
你必须添加一个类,继承testing:
TestWithParam<
T>
,其中T就是你需要参数化的参数类型,比如上面的例子,我需要参数化一个int型的参数
classIsPrimeParamTest:
public:
int>
2.告诉gtest你拿到参数的值后,具体做些什么样的测试
这里,我们要使用一个新的宏(嗯,挺兴奋的):
TEST_P,关于这个"
P"
的含义,Google给出的答案非常幽默,就是说你可以理解为”parameterized"
或者"
pattern"
。
我更倾向于”parameterized"
的解释,呵呵。
在TEST_P宏里,使用GetParam()获取当前的参数的具体值。
TEST_P(IsPrimeParamTest,HandleTrueReturn)
{intn=GetParam();
EXPECT_TRUE(IsPrime(n));
嗯,非常的简洁!
3.告诉gtest你想要测试的参数范围是什么
使用INSTANTIATE_TEST_CASE_P这宏来告诉gtest你要测试的参数范围:
INSTANTIATE_TEST_CASE_P(TrueReturn,IsPrimeParamTest,testing:
Values(3,5,11,23,17));
第一个参数是测试案例的前缀,可以任意取。
第二个参数是测试案例的名称,需要和之前定义的参数化的类的名称相同,如:
IsPrimeParamTest
第三个参数是可以理解为参数生成器,上面的例子使用test:
Values表示使用括号内的参数。
Google提供了一系列的参数生成的函数:
Range(begin,end[,step])
范围在begin~end之间,步长为step,不包括end
Values(v1,v2,...,vN)
v1,v2到vN的值
ValuesIn(container)andValuesIn(begin,end)
从一个C类型的数组或是STL容器,或是迭代器中取值
Bool()
取false和true两个值
Combine(g1,g2,...,gN)
这个比较强悍,它将g1,g2,...gN进行排列组合,g1,g2,...gN本身是一个参数生成器,每次分别从g1,g2,..gN中各取出一个值,组合成一个元组(Tuple)作为一个参数。
说明:
这个功能只在提供了<
tr1/tuple>
头的系统中有效。
gtest会自动去判断是否支持tr/tuple,如果你的系统确实支持,而gtest判断错误的话,你可以重新定义宏GTEST_HAS_TR1_TUPLE=1。
4、参数化后的测试案例名
因为使用了参数化的方式执行案例,我非常想知道运行案例时,每个案例名称是如何命名的。
我执行了上面的代码,输出如下:
从上面的框框中的案例名称大概能够看出案例的命名规则,对于需要了解每个案例的名称的我来说,这非常重要。
命名规则大概为:
prefix/
5、类型参数化
gtest还提供了应付各种不同类型的数据时的方案,以及参数化类型的方案。
我个人感觉这个方案有些复杂。
首先要了解一下类型化测试,就用gtest里的例子了。
首先定义一个模版类,继承testing:
Test:
Test{public:
typedefstd:
list<
List;
staticTshared_;
Tvalue_;
接着我们定义需要测试到的具体数据类型,比如下面定义了需要测试char,int和unsignedint:
typedeftesting:
Types<
char,int,unsignedint>
MyTypes;
TYPED_TEST_CASE(FooTest,MyTypes);
又是一个新的宏,来完成我们的测试案例,在声明模版的数据类型时,使用TypeParam
TYPED_TEST(FooTest,DoesBlah){Sincewearei
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- GTest 使用手册