1、简介
死亡测试的“死亡”指的是程序的崩溃。通常在测试过程中,我们需要考虑各种各样的输入,有的输入可能直接导致程序崩溃,这时我们就需要检查程序是否按照预期的方式挂掉,这也就是所谓的“死亡测试”。gtest的死亡测试能做到在一个安全的环境下执行崩溃的测试案例,同时又对崩溃结果进行验证。
2、相关的宏
ASSERT_DEATH(statement, regex`); EXPECT_DEATH(statement, regex`); 语句因给定错误而崩溃
ASSERT_EXIT(statement, predicate, regex`); EXPECT_EXIT(statement, predicate, regex`); 语句以给定的错误退出,其退出代码与谓词匹配
有一些异常只在Debug下抛出,因此还提供了*_DEBUG_DEATH,用来处理Debug和Realease下的不同。
3、*_DEATH(statement, regex`)
statement:被测试的代码语句
regex:一个正则表达式,用来匹配异常时在stderr中输出的内容
注意:编写死亡测试案例时,TEST的第一个参数,即testcase_name,请使用DeathTest后缀。原因是gtest会优先运行死亡测试案例,应该是为线程安全考虑。
4、*_EXIT(statement, predicate, regex`)
statement:被测试的代码语句
predicate :必须是一个委托,接收int型参数,并返回bool。只有当返回值为true时,死亡测试案例才算通过。
regex:一个正则表达式,用来匹配异常时在stderr中输出的内容
4.1 常用的predicate
testing::ExitedWithCode(exit_code): 如果程序正常退出并且退出码与exit_code相同则返回 true
testing::KilledBySignal(signal_number): // Windows下不支持:如果程序被signal_number信号kill的话就返回true
注意:*_DEATH其实是对*_EXIT进行的一次包装,*_DEATH的predicate判断进程是否以非0退出码退出或被一个信号杀死。
示例:EXPECT_EXIT(_exit(1), testing::ExitedWithCode(1), "");
5、*_DEBUG_DEATH
5.1 定义
#ifdef NDEBUG
#define EXPECT_DEBUG_DEATH(statement, regex) \
do { statement; } while (false)
#define ASSERT_DEBUG_DEATH(statement, regex) \
do { statement; } while (false)
#else
#define EXPECT_DEBUG_DEATH(statement, regex) \
EXPECT_DEATH(statement, regex)
#define ASSERT_DEBUG_DEATH(statement, regex) \
ASSERT_DEATH(statement, regex)
#endif // NDEBUG for EXPECT_DEBUG_DEATH
在Debug版和Release版本下, *_DEBUG_DEATH的定义不一样。因为很多异常只会在Debug版本下抛出,而在Realease版本下不会抛出,所以针对Debug和Release分别做了不同的处理。
5.2 gtest自带的例子
int DieInDebugElse12(int* sideeffect) {
if (sideeffect) *sideeffect = 12;
#ifndef NDEBUG
GTEST_LOG_(FATAL, "debug death inside DieInDebugElse12()");
#endif // NDEBUG
return 12;
}
TEST(TestCase, TestDieOr12WorksInDgbAndOpt)
{
int sideeffect = 0;
// Only asserts in dbg.
EXPECT_DEBUG_DEATH(DieInDebugElse12(&sideeffect), "death");
#ifdef NDEBUG
// opt-mode has sideeffect visible.
EXPECT_EQ(12, sideeffect);
#else
// dbg-mode no visible sideeffect.
EXPECT_EQ(0, sideeffect);
#endif
}
6、正则表达式
在Windows系统中,gtest的死亡测试中使用的是gtest自己实现的简单的正则表达式语法。 相比POSIX风格,gtest的简单正则表达式少了很多内容,比如 ("x|y"), ("(xy)"), ("[xy]") 和("x{5,7}")都不支持。
gtest定义了2个宏,用来表示当前系统支持哪套正则表达式风格:
POSIX风格:GTEST_USES_POSIX_RE = 1
Simple风格:GTEST_USES_SIMPLE_RE=1
6.1 简单正则表达式支持的内容
匹配任何文字字符c
\\d 匹配任何十进制数字
\\D 匹配任何不是十进制数字的字符
\\f 匹配项\f
\\n 匹配项 \n
\\r 匹配项 \r
\\s 匹配任何ASCII空格,包括 \n
\\S 匹配任何非空白字符
\\t 匹配项\t
\\v 匹配项\v
\\w 匹配任何字母、_或十进制数字
\\W 匹配任何不匹配\\w的字符
\\c 匹配任何标点符号文本字符c
. 匹配字符除 \n外
A? 匹配A中0个或1个
A* 匹配A中0个或多个
A+ 匹配A中一个或多个
^ 匹配字符串的开头(不是每行的开头)
$ 匹配字符串的结尾(不是每行的结尾)
xy 匹配跟y的x
7、死亡测试运行方式
1)fast方式(默认的方式)
testing::FLAGS_gtest_death_test_style = "fast";
2)threadsafe方式
testing::FLAGS_gtest_death_test_style = "threadsafe";
可以在 main() 里为所有的死亡测试设置测试形式,也可以为某次测试单独设置。Google Test会在每次测试之前保存这个标记并在测试完成后恢复。
7.1 示例
TEST(MyDeathTest, TestOne) {
testing::FLAGS_gtest_death_test_style = "threadsafe";
// 该测试案例运行在threadsafe方式
ASSERT_DEATH(ThisShouldDie(), "");
}
TEST(MyDeathTest, TestTwo) {
// 该测试案例运行在fast默认方式
ASSERT_DEATH(ThisShouldDie(), "");
}
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
testing::FLAGS_gtest_death_test_style = "fast";
return RUN_ALL_TESTS();
}
8、注意事项
1)不要在死亡测试里释放内存
2)在父进程里再次释放内存
3)不要在程序中使用内存堆检查