为什么选择谷歌cpp测试框架?
Google C++ Testing Framework帮助你更高地写C++类.
无论什么平台,这个框架都可以帮到你.所以,什么是一个好的测试框架?GoogleTest怎么做的?我们相信一下原则:
1.测试具有独立性和重复性.如果一个测试会依赖其他测试的结果,这会是很痛苦的.GoogleTest的每一个测试都运行在不同的对象下.如果一个测试失败了,GoogleTest允许你在一个隔离的环境下进行快速调试.
2.测试代码很好地组织,并且结构清晰.
3.Test应该能重用.
4.当测试失败了,能够提供足够多的信息.
5.测试框架能让测试工程师专注于书写测试代码.
6.测试足够快.
GoogleTest基于流行的xUnit架构,所以如果你用过JUint或者PyUnit,会很容易使用这个框架.如果没有用过,那就花10分钟,看这份文档吧.
建立一个新测试项目
如果用GoogleTest测试一个程序,你需要把GoogleTest编译成一个lib,并且在你的测试里引用这个lib.我们提供了一些构建工具,比如CMake的CMakeLists.txt(在GoogleTest项目的根目录下).一旦你编译好了GoogleTest库,就可以开始创建测试项目了.如果你还有疑问,可以参考GoogleTest自己的测试项目,并把它们当作例子来使用.
基本概念
使用GoogleTest,从写assertions开始,断言(assertions)就是一些判断真假的语句.一句断言的结果,可以是success, nonfatal failure, fatal failure.如果最后一种情况发生了,它会终止当前函数.而前两钟情况,程序会继续运行.
Tests使用断言来或者被测试代码的状态.如果一个测试用例失败了,整个测试也就失败了,否则,就测试通过了.
一个测试用例包含一个或者多个测试.你最好把多个测试分成很多组测试用例,这样可以体现测试代码的结构.如果一个测试用例中的多个测试共享同一个对象或者子程序时,可以考虑把这些测试放入一个test fixture类里面.
一个测试程序可以包含多个测试用例.
接下来介绍怎么写一个测试程序,从各个单独的断言到整个测试用例.
断言
GoogleTest断言是宏定义,模仿函数的调用.你可以通过创建断言来模仿它的行为.如果断言失败了,GoogleTest打印出断言没通过的源文件和行号,还有一句失败的信息.
有两种断言方式:ASSERT_ * 和EXPECT_* ,前者如果错误,抛出的是fatal failure,程序会终止;后者抛出的是nonfatal failure,程序会继续运行.一般推荐用后者,因为这样可以同时测试多个用例.如果一个测试失败,剩下的测试结果没有意义,那就用第一种.
由于ASSERT_会立即终止程序,所以一旦出现这种情况,它不会清除堆上的调用信息.所以如果你发现了堆检查错误和断言错误同时发生,要记住这一点.
如何提供测试失败时的打印消息呢?像这样:
ASSERT_EQ(x.size(), y.size()) << “Vector x and y are of unequal length”;
C风格的字符串和string都可以用<<输出.
基本断言
真假
二值比较断言
字符串比较
更多的断言,看这里.
简单的测试
1.使用TEST()来定义一个测试函数.这是一种没有返回值的常规C++函数.
2.在TEST()里面,写各种断言来测试函数或者类.
3.测试的结果取决于函数里面各个断言的结果.
TEST()有两个参数,第一个是测试用例的名字,第二个是这个测试用例下测试的名字.我们之前说过,一个测试用例可以有很多个测试.名字不要有下划线.这其实就是测试代码的一种组织方式.不同测试用例里的测试可以有相同的名字.例如:
int Factorial(int n);
TEST(FactorialTest, HandleZeroInput){
EXPECT_EQ(1, Factorial(0));
}
TEST(FactorialTest, HandlePositiveInput){
EXPECT_EQ(1, Factorial(1));
EXPECT_EQ(1, Factorial(2));
EXPECT_EQ(1, Factorial(3));
EXPECT_EQ(1, Factorial(4));
}
逻辑相关的测试可以放在同一个测试用例里面,也即是说,第一个参数相同.
TEST Fixtures为多个测试提供相同的数据(多用于类的测试)
(暂时还没用来,先跳过.)
调用这些测试
TEST()和TEST_F()都隐士地注册了这些测试.所以不想其他cpp测试框架需要自己手动列出这些测试,gtest都帮你做了.
定义了测试之后,你可以通过RUN_ALL_TESTS()来运行这些测试.如果全部成功,返回1,否则返回0.RUN_ALL_TESTS()在链接单元里运行所有的测试,这些测试可以来自不同的测试类,甚至不同的测试源文件.
当调用这个函数时,它做了下面这些事情:
1.保存GoogleTest的全部状态值.
2.为第一个测试创建一个测试对象.
3.通过Setup()初始化.
4.在测试对象上运行.
5.通过TearDown()清除所有的测试对象.
6.删除测试对象.
7.回复GoogleTest状态值.
8.为下一次测试重复上述步骤,直至测试全部结束.
另外,任何fatal failure会终止上述过程.
重要:不要忽略RUN_ALL_TESTS()的返回值,否则gcc会报一个错误.这样设计的原因是,整个自动测试框架通过这个返回值判断一个测试是否结束了,而不是测试的打印输出.所以,你的main()函数一定要返回RUN_ALL_TESTS()的返回值.
另外,RUN_ALL_TESTS()只调用一次就够了.