测试驱动开发TDD六Start Google Test in Windows

一、前言
本篇将介绍一些gtest的基本使用,包括下载,安装,编译,建立我们第一个测试Demo工程,以及编写一个最简单的测试案例。
二、下载
如果不记得网址, 直接在google里搜gtest,第一个就是。目前gtest的最新版本为1.3.0,从下列地址可以下载到该最新版本:
http://googletest.googlecode.com/files/gtest-1.3.0.zip


http://googletest.googlecode.com/files/gtest-1.3.0.tar.gz


http://googletest.googlecode.com/files/gtest-1.3.0.tar.bz2


三、编译
下载解压后, 里面有个msvc目录:



使用VS的同学可以直接打开msvc里面的工程文件, 如果你在使用的是VS2005或是VS2008,打开后会提示你升级,升完级后,我们直接编译里面的“gtest”工程,可以直接编过的。
这里要提醒一下的是,如果你升级为VS2008的工程,那么你的测试Demo最好也是VS2008工程,不然你会发现很郁闷,你的Demo怎么也编不过,我也曾折腾了好久,当时我升级为了VS2008工程,结果我使用VS2005工程建Demo,死活编不过。(这里有人误解了,并不是说只能在VS2008中编译,在VS2005中同样可以。如果要编译VS2005版本,最好保证gtest和你的测试工程都使用VS2005工程。)


编译之后,在msvc里面的Debug或是Release目录里看到编译出来的gtestd.lib或是gtest.lib文件。
四、第一个Demo
下面我们开始建立我们的第一个Demo了,假如之前使用的VS2008编译的gtest,那么,我们在VS2008中,新建一个Win32 Console Application。接着就是设置工程属性,总结如下:




1.Runtime Library设置

这里的设置要保证和编译gtest时的设置一致

1.1 假设gtest的设置是这样:

那么你的project设置也应该这样:



2.设置gtest头文件路径 和设置gtest.lib路径

3.1 拷贝头文件:把 gtest目录下面的include目录中的gtest文件夹放到你的$(SCP_ROOT)\include文件夹中

3.2 拷贝库文件:把编译好的gtestd.lib静态库文件拷贝到你的project输出目录中





如果是Release版本,Runtime Library设为/MT。当然,其实你也可以选择动态链接(/MD),前提是你之前编译的gtest也使用了同样是/MD选项。
工程设置后了后,我们来编写一个最简单测试案例试试,我们先来写一个被测试函数:

int Foo(int a,int b)
{
    if (a == 0 || b == 0)
    {
        throw "don't do that";
    }
    int c = a % b;
    if (c == 0)
        return b;
    return Foo(b,c);
}






没错,上面的函数是用来求最大公约数的。下面我们就来编写一个简单的测试案例。

#include <gtest/gtest.h>
#include "ace/Log_Msg.h"
int Foo(int a,int b)
{
	if (a == 0 || b == 0)
	{
		throw "don't do that";
	}
	int c = a % b;
	if (c == 0)
		return b;
	return Foo(b,c);
}

TEST(FooTest,HandleNoneZeroInput)
{
	EXPECT_EQ(2,Foo(4,10));
	EXPECT_EQ(6,Foo(30,18));
}

int ACE_TMAIN(int argc,ACE_TCHAR* argv[])
{
	testing::InitGoogleTest(&argc,argv);
	return RUN_ALL_TESTS();

}



上面可以看到,编写一个测试案例是多么的简单。 我们使用了TEST这个宏,它有两个参数,官方的对这两个参数的解释为:[TestCaseName,TestName],而我对这两个参数的定义是:[TestSuiteName,TestCaseName],在下一篇我们再来看为什么这样定义。
对检查点的检查,我们上面使用到了EXPECT_EQ这个宏,这个宏用来比较两个数字是否相等。Google还包装了一系列EXPECT_* 和ASSERT_*的宏,而EXPECT系列和ASSERT系列的区别是:


1. EXPECT_* 失败时,案例继续往下执行。


2. ASSERT_* 失败时,直接在当前函数中返回,当前函数中ASSERT_*后面的语句将不会执行。
在下一篇,我们再来具体讨论这些断言宏。为了让我们的案例运行起来,我们还需要在main函数中添加如下代码:

上面的代码假设你使用了ACE库,如果不是用,你的main应该像下面这样:


int _tmain(int argc,_TCHAR* argv[])
{
    testing::InitGoogleTest(&argc,argv);
    return RUN_ALL_TESTS();
}


“testing::InitGoogleTest(&argc,argv);” :gtest的测试案例允许接收一系列的命令行参数,因此,我们将命令行参数传递给gtest,进行一些初始化操作。gtest的命令行参数非常丰富,在后面我们也会详细了解到。
“RUN_ALL_TESTS()” :运行所有测试案例


OK,一切就绪了,我们直接运行案例试试(一片绿色,非常爽):



五、总结
本篇内容确实是非常的初级,目的是让从来没有接触过gtest的同学了解gtest最基本的使用。gtest还有很多更高级的使用方法,我们将会在后面讨论。总结本篇的内容的话:


1. 使用VS编译gtest.lib文件


2. 设置测试工程的属性(头文件,lib文件,/MT参数(和编译gtest时使用一样的参数就行了))


3. 使用TEST宏开始一个测试案例,使用EXPECT_*,ASSER_*系列设置检查点。


4. 在Main函数中初始化环境,再使用RUN_ALL_TEST()宏运行测试案例。
优点:


1. 我们的测试案例本身就是一个exe工程,编译之后可以直接运行,非常的方便。


2. 编写测试案例变的非常简单(使用一些简单的宏如TEST),让我们将更多精力花在案例的设计和编写上。


3. 提供了强大丰富的断言的宏,用于对各种不同检查点的检查。


4. 提高了丰富的命令行参数对案例运行进行一系列的设置。

参考:

3.Runtime Library设置

这里的设置要保证和编译gtest时的设置一致



http://www.cnblogs.com/coderzh/archive/2009/03/31/1426758.html

3.Runtime Library设置

这里的设置要保证和编译gtest时的设置一致

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


什么是设计模式一套被反复使用、多数人知晓的、经过分类编目的、代码 设计经验 的总结;使用设计模式是为了 可重用 代码、让代码 更容易 被他人理解、保证代码 可靠性;设计模式使代码编制  真正工程化;设计模式使软件工程的 基石脉络, 如同大厦的结构一样;并不直接用来完成代码的编写,而是 描述 在各种不同情况下,要怎么解决问题的一种方案;能使不稳定依赖于相对稳定、具体依赖于相对抽象,避免引
单一职责原则定义(Single Responsibility Principle,SRP)一个对象应该只包含 单一的职责,并且该职责被完整地封装在一个类中。Every  Object should have  a single responsibility, and that responsibility should be entirely encapsulated by t
动态代理和CGLib代理分不清吗,看看这篇文章,写的非常好,强烈推荐。原文截图*************************************************************************************************************************原文文本************
适配器模式将一个类的接口转换成客户期望的另一个接口,使得原本接口不兼容的类可以相互合作。
策略模式定义了一系列算法族,并封装在类中,它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
设计模式讲的是如何编写可扩展、可维护、可读的高质量代码,它是针对软件开发中经常遇到的一些设计问题,总结出来的一套通用的解决方案。
模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中,使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
迭代器模式提供了一种方法,用于遍历集合对象中的元素,而又不暴露其内部的细节。
外观模式又叫门面模式,它提供了一个统一的(高层)接口,用来访问子系统中的一群接口,使得子系统更容易使用。
单例模式(Singleton Design Pattern)保证一个类只能有一个实例,并提供一个全局访问点。
组合模式可以将对象组合成树形结构来表示“整体-部分”的层次结构,使得客户可以用一致的方式处理个别对象和对象组合。
装饰者模式能够更灵活的,动态的给对象添加其它功能,而不需要修改任何现有的底层代码。
观察者模式(Observer Design Pattern)定义了对象之间的一对多依赖,当对象状态改变的时候,所有依赖者都会自动收到通知。
代理模式为对象提供一个代理,来控制对该对象的访问。代理模式在不改变原始类代码的情况下,通过引入代理类来给原始类附加功能。
工厂模式(Factory Design Pattern)可细分为三种,分别是简单工厂,工厂方法和抽象工厂,它们都是为了更好的创建对象。
状态模式允许对象在内部状态改变时,改变它的行为,对象看起来好像改变了它的类。
命令模式将请求封装为对象,能够支持请求的排队执行、记录日志、撤销等功能。
备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。 基本介绍 **意图:**在不破坏封装性的前提下,捕获一个对象的内部状态,并在该
顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为
享元模式(Flyweight Pattern)(轻量级)(共享元素)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结