Google测试框架入门文档格式.docx

上传人:b****6 文档编号:21632488 上传时间:2023-01-31 格式:DOCX 页数:12 大小:24.52KB
下载 相关 举报
Google测试框架入门文档格式.docx_第1页
第1页 / 共12页
Google测试框架入门文档格式.docx_第2页
第2页 / 共12页
Google测试框架入门文档格式.docx_第3页
第3页 / 共12页
Google测试框架入门文档格式.docx_第4页
第4页 / 共12页
Google测试框架入门文档格式.docx_第5页
第5页 / 共12页
点击查看更多>>
下载资源
资源描述

Google测试框架入门文档格式.docx

《Google测试框架入门文档格式.docx》由会员分享,可在线阅读,更多相关《Google测试框架入门文档格式.docx(12页珍藏版)》请在冰豆网上搜索。

Google测试框架入门文档格式.docx

本文偶尔会用“GoogleTest”来代指“GoogleC++测试框架”。

基本概念

使用GoogleTest时,你是从编写断言开始的,而断言是一些检查条件是否为真的语句。

一个断言的结果可能是成功、非致命失败,或者致命失败。

如果一个致命失败出现,他会结束当前的函数;

否则,程序继续正常运行。

测试使用断言来验证被测代码的行为。

如果一个测试崩溃或是出现一个失败的断言,那么,该测试失败;

否则该测试成功。

一个测试案例(testcase)包含了一个或多个测试。

你应该将自己的测试分别归类到测试案例中,以反映被测代码的结构。

当测试案例中的多个测试需要共享通用对象和子程序时,你可以把他们放到一个测试固件(testfixture)类中。

一个测试程序可以包含多个测试案例。

从编写单个的断言开始,到创建测试和测试案例,我们将会介绍怎样编写一个测试程序。

断言

GoogleTest中的断言是一些与函数调用相似的宏。

要测试一个类或函数,我们需要对其行为做出断言。

当一个断言失败时,GoogleTest会在屏幕上输出该代码所在的源文件及其所在的位置行号,以及错误信息。

也可以在编写断言时,提供一个自定义的错误信息,这个信息在失败时会被附加在GoogleTest的错误信息之后。

断言常常成对出现,它们都测试同一个类或者函数,但对当前功能有着不同的效果。

ASSERT_*版本的断言失败时会产生致命失败,并结束当前函数。

EXPECT_*版本的断言产生非致命失败,而不会中止当前函数。

通常更推荐使用EXPECT_*断言,因为它们运行一个测试中可以有不止一个的错误被报告出来。

但如果在编写断言如果失败,就没有必要继续往下执行的测试时,你应该使用ASSERT_*断言。

因为失败的ASSERT_*断言会立刻从当前的函数返回,可能会跳过其后的一些的清洁代码,这样也许会导致空间泄漏。

根据泄漏本身的特质,这种情况也许值得修复,也可能不值得我们关心——所以,如果你得到断言错误的同时,还得到了一个堆检查的错误,记住上面我们所说的这一点。

要提供一个自定义的错误消息,只需要使用<

<

操作符,或一个<

操作符的序列,将其输入到框架定义的宏中。

下面是一个例子:

Cpp代码

1.ASSERT_EQ(x.size(),y.size())<

"

Vectorsxandyareofunequallength"

;

2.for(inti=0;

i<

x.size();

++i){

3.EXPECT_EQ(x[i],y[i])<

Vectorsxandydifferatindex"

<

i;

4.}

任何能够被输出到ostream中的信息都可以被输出到一个断言宏中——特别是C字符串和string对象。

如果一个宽字符串(wchar_t*,windows上UNICODE模式TCHAR*或std:

:

wstring)被输出到一个断言中,在打印时它会被转换成UTF-8编码。

基本断言

下面这些断言实现了基本的true/false条件测试。

致命断言

非致命断言

验证条件

ASSERT_TRUE(condition);

EXPECT_TRUE(condition);

condition为真

ASSERT_FALSE(condition);

EXPECT_FALSE(condition);

condition为假

记住,当它们失败时,ASSERT_*产生一个致命失败并从当前函数返回,而EXCEPT_*产生一个非致命失败,允许函数继续运行。

在两种情况下,一个断言失败都意味着它所包含的测试失败。

有效平台:

Linux、Windows、Mac。

二进制比较

本节描述了比较两个值的一些断言。

ASSERT_EQ(expected,actual);

EXPECT_EQ(expected,actual);

expected==actual

ASSERT_NE(val1,val2);

EXPECT_NE(val1,val2);

val1!

=val2

ASSERT_LT(val1,val2);

EXPECT_LT(val1,val2);

val1<

val2

ASSERT_LE(val1,val2);

EXPECT_LE(val1,val2);

ASSERT_GT(val1,val2);

EXPECT_GT(val1,val2);

val1>

ASSERT_GE(val1,val2);

EXPECT_GE(val1,val2);

在出现失败事件时,GoogleTest会将两个值(Val1和Val2)都打印出来。

在ASSERT_EQ*和EXCEPT_EQ*断言(以及我们随后介绍类似的断言)中,你应该把你希望测试的表达式放在actual(实际值)的位置上,将其期望值放在expected(期望值)的位置上,因为GoogleTest的测试消息为这种惯例做了一些优化。

参数值必须是可通过断言的比较操作符进行比较的,否则你会得到一个编译错误。

参数值还必须支持<

操作符来将值输入到ostream中。

所有的C++内置类型都支持这一点。

这些断言可以用于用户自定义的型别,但你必须重载相应的比较操作符(如==、<

等)。

如果定义有相应的操作符,推荐使用ASSERT_*()宏,因为它们不仅会输出比较的结果,还会输出两个比较对象。

参数表达式总是只被解析一次。

因此,参数表达式有一定的副作用(sideeffect,这里应该是指编译器不同,操作符解析顺序的不确定性)也是可以接受的。

但是,同其他普通C/C++函数一样,参数表达式的解析顺序是不确定的(如,一种编译器可以自由选择一种顺序来进行解析),而你的代码不应该依赖于某种特定的参数解析顺序。

ASSERT_EQ()对指针进行的是指针比较。

即,如果被用在两个C字符串上,它会比较它们是否指向同样的内存地址,而不是它们所指向的字符串是否有相同值。

所以,如果你想对两个C字符串(例如,constchar*)进行值比较,请使用ASSERT_STREQ()宏,该宏会在后面介绍到。

特别需要一提的是,要验证一个C字符串是否为空(NULL),使用ASSERT_STREQ(NULL,c_string)。

但是要比较两个string对象时,你应该使用ASSERT_EQ。

本节中介绍的宏都可以处理窄字符串对象和宽字符串对象(string和wstring)。

字符串比较

该组断言用于比较两个C字符串。

如果你想要比较两个string对象,相应地使用EXPECT_EQ、EXPECT_NE等断言。

ASSERT_STREQ(expected_str,actual_str);

EXPECT_STREQ(expected_str,actual_str);

两个C字符串有相同的内容

ASSERT_STRNE(str1,str2);

EXPECT_STRNE(str1,str2);

两个C字符串有不同的内容

ASSERT_STRCASEEQ(expected_str,actual_str);

EXPECT_STRCASEEQ(expected_str,actual_str);

两个C字符串有相同的内容,忽略大小写

ASSERT_STRCASENE(str1,str2);

EXPECT_STRCASENE(str1,str2);

两个C字符串有不同的内容,忽略大小写

注意断言名称中出现的“CASE”意味着大小写被忽略了。

*STREQ*和*STRNE*也接受宽字符串(wchar_t*)。

如果两个宽字符串比较失败,它们的值会做为UTF-8窄字符串被输出。

一个NULL空指针和一个空字符串会被认为是不一样的。

参见:

更多的字符串比较的技巧(如子字符串、前缀和正则表达式匹配),请参见[AdvancedGuideAdvancedGoogleTestGuide]。

简单的测试

要创建一个测试:

1.使用TEST()宏来定义和命名一个测试函数,它们是一些没有返回值的普通C++函数。

2.在这个函数中,与你想要包含的其它任何有效C++代码一起,使用GoogleTest提供的各种断言来进行检查。

3.测试的结果由其中的断言决定;

如果测试中的任意断言失败(无论是致命还是非致命),或者测试崩溃,那么整个测试就失败了。

否则,测试通过。

1.TEST(test_case_name,test_name){

2....testbody...

3.}

TEST()的参数是从概括到特殊的。

第一个参数是测试案例的名称,第二个参数是测试案例中的测试的名称。

记住,一个测试案例可以包含任意数量的独立测试。

一个测试的全称包括了包含它的测试案例名称,及其独立的名称。

不同测试案例中的独立测试可以有相同的名称。

举例来说,让我们看一个简单的整数函数:

1.intFactorial(intn);

//返回n的阶乘

这个函数的测试案例应该看起来像是:

1.//测试0的阶乘

2.TEST(FactorialTest,HandlesZeroInput){

3.EXPECT_EQ(1,Factorial(0));

5.//测试正数的阶乘

6.TEST(FactorialTest,HandlesPositiveInput){

7.EXPECT_EQ(1,Factorial

(1));

8.EXPECT_EQ(2,Factorial

(2));

9.EXPECT_EQ(6,Factorial(3));

10.EXPECT_EQ(40320,Factorial(8));

11.}

GoogleTest根据测试案例来分组收集测试结果,因此,逻辑相关的测试应该在同一测试案例中;

换句话说,它们的TEST()的第一个参数应该是一样的。

在上面的例子中,我们有两个测试,HandlesZeroInput和HandlesPostiveInput,它们都属于同一个测试案例FactorialTest。

测试固件(TestFixtures,又做测试夹具、测试套件):

在多个测试中使用同样的数据配置

当你发现自己编写了两个或多个测试来操作同样的数据,你可以采用一个测试固件。

它让你可以在多个不同的测试中重用同样的对象配置。

要创建测试固件,只需:

1.创建一个类继承自testing:

Test。

将其中的成员声明为protected:

或是public:

,因为我们想要从子类中存取固件成员。

2.在该类中声明你计划使用的任何对象。

3.如果需要,编写一个默认构造函数或者SetUp()函数来为每个测试准备对象。

常见错误包括将SetUp()拼写为Setup()(小写了u)——不要让它发生在你身上。

4.如果需要,编写一个析构函数或者TearDown()函数来释放你在SetUp()函数中申请的资源。

要知道什么时候应该使用构造函数/析构函数,什么时候又应该使用SetUp()/TearDown()函数,阅读我们的FAQ。

5.如果需要,定义你的测试所需要共享的子程序。

当我们要使用固件时,使用TEST_F()替换掉TEST(),它允许我们存取测试固件中的对象和子程序:

1.TEST_F(test_case_name,test_name){

与TEST()一样,第一个参数是测试案例的名称,但对TEST_F()来说,这个名称必须与测试固件类的名称一些。

你可能已经猜到了:

_F正是指固件。

不幸地是,C++宏系统并不允许我们创建一个单独的宏来处理两种类型的测试。

使用错误的宏会导致编译期的错误。

而且,你必须在TEST_F()中使用它之前,定义好这个测试固件类。

否则,你会得到编译器的报错:

“virtualoutsideclassdeclaration”。

对于TEST_F()中定义的每个测试,GoogleTest将会:

1.在运行时创建一个全新的测试固件

2.马上通过SetUp()初始化它,

3.运行测试

4.调用TearDown()来进行清理工作

5.删除测试固件。

注意,同一测试案例中,不同的测试拥有不同的测试固件。

GoogleTest在创建下一个测试固件前总是会对现有固件进行删除。

GoogleTest不会对多个测试重用一个测试固件。

测试对测试固件的改动并不会影响到其他测试。

例如,让我们为一个名为Queue的FIFO队列类编写测试,该类的接口如下:

1.template<

typenameE>

//E为元素类型

2.classQueue{

3.public:

4.Queue();

5.voidEnqueue(constE&

element);

6.E*Dequeue();

//返回NULL如果队列为空.

7.size_tsize()const;

8....

9.};

首先,定义一个固件类。

习惯上,你应该把它的名字定义为FooTest,这里的Foo是被测试的类。

1.classQueueTest:

publictesting:

Test{

2.protected:

3.virtualvoidSetUp(){

4.q1_.Enqueue

(1);

5.q2_.Enqueue

(2);

6.q2_.Enqueue(3);

7.}

8.//virtualvoidTearDown(){}

9.Queue<

int>

q0_;

10.Queue<

q1_;

11.Queue<

q2_;

12.};

在这个案例中,我们不需要TearDown(),因为每个测试后除了析构函数外不需要进行其它的清理工作了。

接下来我们使用TEST_F()和这个固件来编写测试。

1.TEST_F(QueueTest,IsEmptyInitially){

2.EXPECT_EQ(0,q0_.size());

4.TEST_F(QueueTest,DequeueWorks){

5.int*n=q0_.Dequeue();

6.EXPECT_EQ(NULL,n);

7.

8.n=q1_.Dequeue();

9.ASSERT_TRUE(n!

=NULL);

10.EXPECT_EQ(1,*n);

11.EXPECT_EQ(0,q1_.size());

12.deleten;

13.

14.n=q2_.Dequeue();

15.ASSERT_TRUE(n!

16.EXPECT_EQ(2,*n);

17.EXPECT_EQ(1,q2_.size());

18.deleten;

19.}

上面这段代码既使用了ASSERT_*断言,又使用了EXPECT_*断言。

经验上讲,如果你想要断言失败后,测试能够继续进行以显示更多的错误时,你应该使用EXPECT_*断言;

使用ASSERT_*如果该断言失败后继续往下执行毫无意义。

例如,Dequeue测试中的第二个断言是ASSERT_TURE(n!

=NULL),因为我们随后会n指针解引用,如果n指针为空的话,会导致一个段错误。

当这些测试开始时,会发生如下情况:

1.GoogleTest创建一个QueueTest对象(我们把它叫做t1)。

2.t1.SetUp()初始化t1。

3.第一个测试(IsEmptyInitiallly)在t1上运行。

4.测试完成后,t1.TearDown()进行一些清理工作。

5.t1被析构。

6.以上步骤在另一个QueueTest对象上重复进行,这回会运行DequeueWorks测试。

注意:

当一个测试对象被构造时,GoogleTest会自动地保存所有的GoogleTest变量标识,对象析构后进行恢复。

调用测试

TEST()和TEST_F()向GoogleTest隐式注册它们的测试。

因此,与很多其他的C++测试框架不同,你不需要为了运行你定义的测试而将它们全部再列出来一次。

在定义好测试后,你可以通过RUN_ALL_TESTS()来运行它们,如果所有测试成功,该函数返回0,否则会返回1.注意RUN_ALL_TESTS()会运行你链接到的所有测试——它们可以来自不同的测试案例,甚至是来自不同的文件。

当被调用时,RUN_ALL_TESTS()宏会:

1.保存所有的GoogleTest标志。

2.为一个侧测试创建测试固件对象。

3.调用SetUp()初始化它。

4.在固件对象上运行测试。

5.调用TearDown()清理固件。

6.删除固件。

7.恢复所有GoogleTest标志的状态。

8.重复上诉步骤,直到所有测试完成。

此外,如果第二步时,测试固件的构造函数产生一个致命错误,继续执行3至5部显然没有必要,所以它们会被跳过。

与之相似,如果第3部产生致命错误,第4部也会被跳过。

重要:

你不能忽略掉RUN_ALL_TESTS()的返回值,否则gcc会报一个编译错误。

这样设计的理由是自动化测试服务会根据测试退出返回码来决定一个测试是否通过,而不是根据其stdout/stderr输出;

因此你的main()函数必须返回RUN_ALL_TESTS()的值。

而且,你应该只调用RUN_ALL_TESTS()一次。

多次调用该函数会与GoogleTest的一些高阶特性(如线程安全死亡测试thread-safedeathtests)冲突,因而是不被支持的。

编写main()函数

你可以从下面这个样板开始:

1.#include"

this/package/foo.h"

2.#include<

gtest/gtest.h>

3.namespace{

4.//测试Foo类的测试固件

5.classFooTest:

6.protected:

7.//Youcanremoveanyorallofthefollowingfunctionsifitsbody

8.//isempty.

9.FooTest(){

10.//Youcandoset-upworkforeachtesthere.

11.}

12.virtual~FooTest(){

13.//Youcandoclean-upworkthatdoesn'

tthrowexceptionshere.

14.}

15.//Iftheconstructoranddestructorarenotenoughforsettingup

16.//andcleaningupeachtest,youcandefinethefollowingmethods:

17.virtualvoidSetUp(){

18.//Codeherewillbecalledimmediatelyaftertheconstructor(right

19.//beforeeachtest).

20.}

21.virtualvoidTearDown(){

22.//Codeherewillbecalledimmediatelyaftereachtest(right

23.//beforethedestructor).

24.}

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

当前位置:首页 > 高等教育 > 管理学

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

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