目录
一、简介
MySQL的Unittest模块是使用Google的开源C++单元测试框架GoogleTest(简称Gtest)撰写。Gtest是基于xUnit架构的测试框架,具有丰富的断言集,能够进行死亡测试、致命与非致命的失败判断和类型参数化测试等,支持各类运行测试的选项和XML格式的测试报告,支持测试用例的自动注册。Gtest将最常用的单元测试功能封装成了带参数的宏,通过在不同的对象上运行每个测试来隔离测试,实现测试的独立和可重复。Gtest简洁容易上手,实用性较为突出。
在MySQL源码目录下有unittest目录,下有examples、gunit、mytap等子目录,其中gunit目录保存大量的测试用例文件。测试用例的文件有固定的格式,一般以-t.cc结尾。新增的测试用例要想集成到MySQL中,需要在CMakeLists.txt SET(TESTS xxx xxx xxx)中添加新增的测试用例文件名称,注意名称应该将-t.cc结尾删去保留剩余的部分。
接下来按照Gtest的叫法,明确解释一些概念术语:
TestCase:测试用例。每个测试用例文件有一个或多个测试用例。
TestSuite:测试套件。给一类相同的测试起相同的名称,用于一些相同的操作。
二、Gtest使用方法
MySQL Unittest单元测试使用Gtest的相关组件,验证不同的传入参数对MySQL某一函数、类等的效果。TestCase是单一测试,TestSuite包含一个或多个测试。当测试套件中的多个测试需要共享公共对象和子例程时,可以将它们放入测试夹具上。一个测试程序可以包含多个TestSuite。
2.1 基本用法
接下来主要介绍如何使用Gtest编写一个MySQL测试用例文件。约定测试用例文件命名方式应以-t.cc后缀严格结尾。
一个完整的测试用例文件包括:
a.头文件: #include<gtest/gtest.h>
#include<gmock/gmock.h>
#include”xxxxxx”
b.命名空间: namespace { }
c.测试用例: TEST()、TEST_F()、TEST_P()、…...
d.main函数(如果不需要的话,可不写)
头文件应该根据需要包含gtest.h或gmock.h,以及其他所要测试的头文件。
命名空间是为了将本文件作为一个整体来看,有名空间、匿名空间都可。
测试用例使用TEST()宏来定义和命名测试函数。
TEST(TestCaseName, TestName) {
... test body ...
}
第一个参数是测试用例的名字,第二个是测试的名字。两个名称都必须是有效的C++标志符,不能使用下划线“_”。{}内是真正实现测试的主体。
TEST()是没有返回值的普通C++函数。连同将要包含的任何有效的C++语句,使用各种Gtest断言检查值,断言写在测试的主体中。TEST宏的作用是创建一个简单测试,它定义了一个测试函数,在这个函数里可以使用任何C++代码,并使用提供封装好的断言来进行检查。
测试的结果由断言决定。Gtest断言是类似于函数调用的宏,可以通过断言类或者函数的行为来测试。当断言失败后,Gtest会打印断言的源文件和行号位置,还有失败信息。也可以自定义失败信息,该消息将附加到Gtest的消息中。
Gtest中的断言有两类,一类是ASSERT系列断言,另一类是EXPECT系列断言,它们成对出现,测试相同的东西,但是对当前函数的影响不同。其中:
EXPECT*允许在一个测试中报告多个失败。失败时,案例继续往下执行。
ASSERT*失败时,直接在当前函数中返回,当前函数中后面的语句不在执行。由于函数直接返回,可能会跳过后面的清理代码,可能会导致内存泄露。
Gtest封装了丰富的断言,有布尔型、数值型、字符串型、浮点型等断言,并且能够显示返回成功或失败。异常检查、predicate assertions、类型检查。下面列出常用的断言,后续会介绍其他断言。
布尔型断言:
Fatal assertion |
Nonfatal assertion |
Verifies |
ASSERT_TRUE(condition); |
EXPECT_TRUE(condition); |
condition is true |
ASSERT_FALSE(condition); |
EXPECT_FALSE(cond |