1、前言
作为一个成熟的单元测试框架,gtest自然拥有一些用于判断值是否与期望一致的断言。在gtest中,断言分为两大类:ASSERT_*和EXPECT_*。它们的区别在于,ASSERT_*类断言在失败时,会立即退出当前的测试用例(即其所在的函数,但不会结束整个测试);EXPECT_*类断言在失败时,会继续执行,不会退出当前测试用例。
在每一个大类中,有分为多个小类别,它们分别用于不同目的的测试,如布尔测试、数值测试、字符串测试等等,下面我们逐个认识gtest中,为它们所定义的宏。
2、布尔测试
布尔测试用于测试给定的值为真还是假,它们包括:
*_TRUE(condition):期望condition为true,若condition为false,则断言失败;
*_FALSE(condition):期望condition为false,若condition为true,则断言失败;
其中“*“为”ASSERT“或者”EXPECT“,后续所有的宏都将采用这种形式。
3、数值比较测试
数值比较测试即比较两个数值之间的大小关系,它们包括:
*_EQ(expected, actual):expected == actual则成功,否则失败;
*_NE(expected, actual):expedted != actual则成功,否则失败;
*_LT(val1, val2):val1 < val2则成功,否则失败;
*_LE(val1, val2):val1 <= val2 则成功,否则失败;
*_GT(val1, val2):val1 > val2则成功,否则失败;
*_GE(val1,val2): val1 >= val2则成功,否则失败;
4、浮点数类型比较
gtest针对浮点数是否相等专门定义了宏,它们包括:
*_FLOAT_EQ(expected, actual):expected与actual相差很小时成功,否则失败;
*_DOUBLE_EQ(expected, actual):expected与actual相差很小时成功,否则失败;
*_NEAR(val1, val2, abs):|val1 - val2| <= abs时成功,否则失败;
5、字符串类型比较
对于字符串,gtest提供字符串相等及不等断言,但它们都只支持C类型的字符串,不支持C++中的std::string和std::wstring,它们包括:
*_STREQ(expected, actual):同时支持char*和wchar_t*,expected和actual的字符串内容相同则成功,否则失败;
*_STRNE(str1, str2):同时支持char*和wchar_t*,str1和str2字符串内容不同则成功,否则失败;
*_STRCASEEQ(expected, actual):只支持char*, expected和actual的字符串内容相同则成功,否则失败;
*_STRCASENE(str1, str2):只支持char*,str1和str2字符串内容不同则成功,否则失败;
6、执行成功与失败标记
在gtest中,测试通过与否有三种状态,它们对应于一个枚举:
enum Type {
kSuccess, // Succeeded.
kNonFatalFailure, // Failed but the test can continue.
kFatalFailure // Failed and the test should be terminated.
};
每一个枚举值都对应一个宏,通过这个宏我们可以返回相应的执行状态:
kSuccess:成功,对应的宏为SUCCEED();
kNonFatalFailure:虽然失败,但当前测试用例的后续测试仍然继续运行,对应ADD_FAIL();
kFatalFailure:致命错误,当前测试用例后续测试不会执行,对应FAIL();
7、异常检查
gtest中提供检查代码是否抛出异常的方法,它们包括:
*_THROW(statement, exception_type):statement如果抛出exception_type类型异常则成功,否则失败;
*_ANY_THROW(statement):只要statement抛出任何异常则成功,否则失败;
*_NO_THROW(statement):只要statement抛出任何异常则失败,否则成功;
8、谓词检查
在gtest中,有一系列的宏,它们第一个参数为运行的函数或可执行体(要求返回值能够转换为bool类型),后续为执行函数所需要的参数,然后这些宏会自动运行这个函数,如果函数返回true则断言成功,否则失败,它们包括:
*_PRED1(pred, param1):pred位可执行体,它接收一个参数,当pred(param1)返回true则断言成功,否则失败;
*_PRED2(pred, param1, param2):pred位可执行体,它接收两个参数,当pred(param1, param2)返回true则断言成功,否则失败;
… …
gtest中最多提供了对5个参数的支持,即从*_PRED1到*_PRED5。如下测试代码:
- bool isEven(int n)
- {
- return !(n & 1);
- }
- TEST(HelloGtest, FirstTest)
- {
- int n = 3;
- EXPECT_PRED1(isEven, n);
- }
bool isEven(int n)
{
return !(n & 1);
}
TEST(HelloGtest, FirstTest)
{
int n = 3;
EXPECT_PRED1(isEven, n);
}
它的运行结果如下图所示:
从图中可以看到,谓词断言比EXPECT_TRUE断言给了更加详细的错误信息,为了方便对比,我们给出EXPECT_TRUE的运行结果:
当然,如果我们队输出的错误信息仍然不满意,还可以使用gtest中的格式化断言,它们包括:
*_PRED_FORMAT1(pred_format1, param1):如果pred_format1(param1)失败,则会按用户自定义的format来输出错误信息;
……(同样支持最多5个参数)
要使用这些宏,我们需要自己额外定义一个函数来提供对错误信息的格式化,依然以判断偶数为例:
- testing::AssertionResult AssertNumberIsEven(const char* n_expr, int n) {
- if (isEven(n))
- return testing::AssertionSuccess();
- testing::Message msg;
- msg << n_expr << ” is not an even number”;
- return testing::AssertionFailure(msg);
- }
- TEST(HelloGtest, FirstTest)
- {
- int n = 3;
- EXPECT_PRED_FORMAT1(AssertNumberIsEven, n);
- }
testing::AssertionResult AssertNumberIsEven(const char* n_expr, int n) {
if (isEven(n))
return testing::AssertionSuccess();
testing::Message msg;
msg << n_expr << " is not an even number";
return testing::AssertionFailure(msg);
}
TEST(HelloGtest, FirstTest)
{
int n = 3;
EXPECT_PRED_FORMAT1(AssertNumberIsEven, n);
}
其中AssertNumberIsEven这个函数即我们需要额外定义的函数,它返回一个testing::AssertionResult,在这个函数中,如果用于*_PRED_FORMAT1,则它最第一个参数为一个const char*类型,用于保存格式化后的错误信息,后续为待测试函数的参数;如果用于*_PRED_FORMAT2,则它前两个参数为const char*,后续两个为函数参数,以此类推…然后在调用*_PRED_FORMAT1时,将这个函数作为第一个参数传给宏即可,后续为待测试函数的参数,不包括上述的字符串。
运行结果如下所示:
9、windows HRESULT检查
它们包括:
*_HRESULT_SUCCEEDED及*_HRESULT_FAILED。
10、类型检查
gtest中的类型检查为testting::StaticAssertTypeEq,它是一个静态检查,主要用于模板编程之中,如果类型检查失败则无法通过编译,这样可以避免在运行时程序出错。这就类似于c++ 11中的static_assert一样。
11、总结
本章我们主要罗列了gtest中的一些断言的宏,及其使用。