gtest的安装和使用
Linux x86环境下
一,gtest安装
下载gtest源码包:gtest-1.7.0.zip
解压后进入gtest-1.7.0目录
cmake CMakeLists.txt
make 后生成两个静态库:libgtest.a libgtest_main.a
sudo cp libgtest*.a /usr/lib
sudo cp –a include/gtest /usr/include
下面是进入到sample目录下编译用例
cd sample
g++ sample1.cc sample1_unittest.cc -lgtest -lgtest_main -lpthread -o test1
g++ sample1.cc sample3-inl.h sample5_unittest.cc -lgtest -lgtest_main -lpthread -o test5
由于sample1.cc和sample1_unittest.cc文件中没有编写main函数,这里需要链接libgtest_main.a库
二,gtest使用
http://www.cnblogs.com/coderzh/archive/2009/04/06/1430364.html
gtest 即 Google C++单元测试框架
单元测试一般由编码人员自己完成,它的目的是隔离程序部件,并证明这些单个部件满足预期的功能。
它提供了丰富的断言、致命和非致命失败判断,能进行值参数化测试、类型参数化测试、“死亡测试”
1,断言
ASSERT_* 系列的断言,当检查点失败时,退出当前函数(注意:并非退出当前案例)
EXPECT_* 系列的断言,当检查点失败时,继续往下执行。
<1>布尔类型检查
ASSERT_TRUE(condition) ASSERT_FALSE(condition)
<2>数值类型检查
ASSERT_EQ(expected, actual);
ASSERT_NE(val1, val2);
ASSERT_LT(val1, val2);
ASSERT_LE(val1, val2);
ASSERT_GT(val1, val2);
ASSERT_GE(val1, val2);
<3>字符串检查
ASSERT_STREQ(expected_str, actual_str);
ASSERT_STRNE(str1, str2);
ASSERT_STRCASEEQ(expected_str, actual_str);
ASSERT_STRCASENE(str1, str2);
一个简单的测试案例,可以参考sample/sample1.cc 和sample1_unittest.cc
另外sample2 是对类的接口函数的测试。
首先是一个求最大公约数的函数
int Foo(int a, int b) |
下面是对这个函数写一个简单的测试样例
#include <gtest/gtest.h> |
每个案例(TEST或TEST_F)应该是相互独立,互不影响的。
TEST宏有两个参数,第一个是TestSuiteName,第二个是TestCaseName
然后在main中添加如下代码让我们的案例运行起来。
int _tmain(int argc, _TCHAR* argv[]) |
也可以不写main函数,直接在编译的时候链接libgtest_main.a库
2,gtest提供了多种事件机制,非常方便我们在案例之前或之后做一些操作。总结一下gtest的事件一共有3种:
<1>全局的,所有案例执行前后。
<2>TestSuite级别的,在某一批案例中第一个案例前,最后一个案例执行后。
<3> TestCase级别的,每个TestCase前后。
这里主要介绍TestCase事件
TestCase事件是挂在每个案例执行前后的,不过需要实现的是SetUp方法和TearDown方法:
1. SetUp()方法在每个TestCase之前执行
2. TearDown()方法在每个TestCase之后执行
要写一个类,这个类继承 testing::Test类。
class FooCalcTest:public testing::Test |
写测试案例时,使用TEST_F则开始测试前调用SetUp,结束案例后调用TearDown。也可以在这个类中定义其他的测试函数,供TEST_F调用。TEST_F的第一个参数类的名字,第二个参数是测试案例名。
gtest源码中的sample3也用的是TestCase事件。这个例子中定义了一个Queue模板,在QueueTest类中定义了SetUp函数和一个用来测试Map的MapTester函数。
3,参数化测试(mytest2)
首先必须添加一个类,继承testing::TestWithParam<T>,其中T就是你需要参数化的参数类型,这里是int。
然后使用TEST_P定义参数化案例。在TEST_P宏里,使用GetParam()获取当前的参数的具体值。
最后 使用INSTANTIATE_TEST_CASE_P这宏来告诉gtest你要测试的参数范围
#include <gtest/gtest.h> |
INSTANTIATE_TEST_CASE_P宏的三个参数:
第一个参数是测试案例的前缀,可以任意取。
第二个参数是测试案例的名称,需要和之前定义的参数化的类的名称相同,如:IsPrimeParamTest
第三个参数是可以理解为参数生成器,上面的例子使用test::Values表示使用括号内的参数。Google提供了一系列的参数生成的函数:
Range(begin, end[, step]) |
范围在begin~end之间,步长为step,不包括end |
Values(v1, v2, ..., vN) |
v1,v2到vN的值 |
ValuesIn(container) and ValuesIn(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,命令行参数
--gtest_output=xml:dir:\foo.xml
指定输出到dir\foo.xml,不指定则输出到当前目录。也可以由系统变量GTEST_OUTPUT指定
--gtest_list_tests
使用这个参数时,将不会执行里面的测试案例,而是输出一个案例的列表。
--gtest_filter
对执行的测试案例进行过滤,支持通配符
好的单元测试具备以下特点:
1, 独立:即该测试用例的测试结果不受其他测试的影响
2, 有效的组织架构,清晰的命名:各个测试用例针对不同的测试对象,而对单个测试对象而言,又可能有多个测试用例对应该对象的多个功能。好的习惯是把这些用例以层次结构的形式组织起来,并使用清晰的命名,使得我们通过阅读用例名称即可明了该用例的功能
3, 可移植、可复用
4, 当用例失败时,提供尽可能多的有效信息