GTest使用手册文档格式.docx

上传人:b****5 文档编号:21490961 上传时间:2023-01-30 格式:DOCX 页数:29 大小:33.82KB
下载 相关 举报
GTest使用手册文档格式.docx_第1页
第1页 / 共29页
GTest使用手册文档格式.docx_第2页
第2页 / 共29页
GTest使用手册文档格式.docx_第3页
第3页 / 共29页
GTest使用手册文档格式.docx_第4页
第4页 / 共29页
GTest使用手册文档格式.docx_第5页
第5页 / 共29页
点击查看更多>>
下载资源
资源描述

GTest使用手册文档格式.docx

《GTest使用手册文档格式.docx》由会员分享,可在线阅读,更多相关《GTest使用手册文档格式.docx(29页珍藏版)》请在冰豆网上搜索。

GTest使用手册文档格式.docx

{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

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 环境科学食品科学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1