`
tibaloga
  • 浏览: 877091 次
文章分类
社区版块
存档分类
最新评论

【转】玩转Google开源C++单元测试框架Google Test系列(gtest)之五 - 死亡测试

 
阅读更多

原文地址:http://www.cnblogs.com/coderzh/archive/2009/04/08/1432043.html

一、前言

“死亡测试”名字比较恐怖,这里的“死亡”指的的是程序的崩溃。通常在测试过程中,我们需要考虑各种各样的输入,有的输入可能直接导致程序崩溃,这 时我们就需要检查程序是否按照预期的方式挂掉,这也就是所谓的“死亡测试”。gtest的死亡测试能做到在一个安全的环境下执行崩溃的测试案例,同时又对 崩溃结果进行验证。

二、使用的宏

Fatal assertion Nonfatal assertion Verifies
ASSERT_DEATH( statement, regex `); EXPECT_DEATH( statement, regex `); statement crashes with the given error
ASSERT_EXIT( statement, predicate, regex `); EXPECT_EXIT( statement, predicate, regex `); statement exits with the given error and its exit code matches predicate

由于有些异常只在Debug下抛出,因此还提供了*_DEBUG_DEATH,用来处理Debug和Realease下的不同。

三、*_DEATH(statement, regex`)

1. statement是被测试的代码语句

2. regex是一个正则表达式,用来匹配异常时在stderr中输出的内容

如下面的例子:

<!-- <br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->void Foo()
{
int * pInt = 0 ;
* pInt = 42 ;
}

TEST(FooDeathTest,Demo)
{
EXPECT_DEATH(Foo(),
"" );
}

重要:编写死亡测试案例时,TEST的第一个参数,即testcase_name,请使用DeathTest后缀。原因是gtest会优先运行死亡测试案例,应该是为线程安全考虑。

四、*_EXIT( statement, predicate, regex `)

1. statement是被测试的代码语句

2. predicate 在这里必须是一个委托,接收int型参数,并返回bool。只有当返回值为true时,死亡测试案例才算通过。gtest提供了一些常用的predicate:

<!-- <br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->testing::ExitedWithCode(exit_code)


如果程序正常退出并且退出码与exit_code相同则返回 true

<!-- <br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->testing::KilledBySignal(signal_number) // Windows下不支持


如果程序被signal_number信号kill的话就返回true

3. regex是一个正则表达式,用来匹配异常时在stderr中输出的内容

这里, 要说明的是,*_DEATH其实是对*_EXIT进行的一次包装,*_DEATH的predicate判断进程是否以非0退出码退出或被一个信号杀死。

例子:

<!-- <br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->TEST(ExitDeathTest,Demo)
{
EXPECT_EXIT(_exit(
1 ),testing::ExitedWithCode( 1 ), "" );
}

五、*_DEBUG_DEATH

先来看定义:

<!-- <br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->#ifdefNDEBUG

#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 // NDEBUGforEXPECT_DEBUG_DEATH

可以看到,在Debug版和Release版本下, *_DEBUG_DEATH的定义不一样。因为很多异常只会在Debug版本下抛出,而在Realease版本下不会抛出,所以针对Debug和Release分别做了不同的处理。看gtest里自带的例子就明白了:

<!-- <br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->int DieInDebugElse12( int * sideeffect){
if (sideeffect) * sideeffect = 12 ;
#ifndefNDEBUG
GTEST_LOG_(FATAL,
" debugdeathinsideDieInDebugElse12() " );
#endif // NDEBUG
return 12 ;
}

TEST(TestCase,TestDieOr12WorksInDgbAndOpt)
{
int sideeffect = 0 ;
// Onlyassertsindbg.
EXPECT_DEBUG_DEATH(DieInDebugElse12( & sideeffect), " death " );

#ifdefNDEBUG
// opt-modehassideeffectvisible.
EXPECT_EQ( 12 ,sideeffect);
#else
// dbg-modenovisiblesideeffect.
EXPECT_EQ( 0 ,sideeffect);
#endif
}

六、关于正则表达式

POSIX系统( Linux, Cygwin, 和 Mac 中,gtest的死亡测试中使用的是POSIX风格的正则表达式, 想了解POSIX风格 表达式可参考:

1. POSIX extended regular expression

2. Wikipedia entry .

在Windows系统中,gtest的死亡测试中使用的是gtest自己实现的简单的正则表达式语法。 相比POSIX风格,gtest的简单正则表达式少了很多内容,比如 ("x|y" ), ("(xy)" ), ("[xy]" ) 和("x{5,7}")都不支持。

下面是简单正则表达式支持的一些内容:


matches any literal character c
//d matches any decimal digit
//D matches any character that's not a decimal digit
//f matches /f
//n matches /n
//r matches /r
//s matches any ASCII whitespace, including /n
//S matches any character that's not a whitespace
//t matches /t
//v matches /v
//w matches any letter, _ , or decimal digit
//W matches any character that //w doesn't match
//c matches any literal character c , which must be a punctuation
. matches any single character except /n
A? matches 0 or 1 occurrences of A
A* matches 0 or many occurrences of A
A+ matches 1 or many occurrences of A
^ matches the beginning of a string (not that of each line)
$ matches the end of a string (not that of each line)
xy matches x followed by y

gtest定义两个宏,用来表示当前系统支持哪套正则表达式风格:

1. POSIX风格:GTEST_USES_POSIX_RE = 1

2. Simple风格:GTEST_USES_SIMPLE_RE=1

七、死亡测试运行方式

1. fast方式(默认的方式)

<!-- <br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->testing::FLAGS_gtest_death_test_style = "fast " ;

2. threadsafe方式

<!-- <br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->testing::FLAGS_gtest_death_test_style = " threadsafe " ;

你可以在 main() 里为所有的死亡测试设置测试形式,也可以为某次测试单独设置。Google Test会在每次测试之前保存这个标记并在测试完成后恢复,所以你不需要去管这部分工作 。如:

<!-- <br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->TEST(MyDeathTest,TestOne){
testing::FLAGS_gtest_death_test_style
= " threadsafe " ;
// Thistestisruninthe"threadsafe"style:
ASSERT_DEATH(ThisShouldDie(), "" );
}

TEST(MyDeathTest,TestTwo){
// Thistestisruninthe"fast"style:
ASSERT_DEATH(ThisShouldDie(), "" );
}

int main( int argc, char ** argv){
testing::InitGoogleTest(
& argc,argv);
testing::FLAGS_gtest_death_test_style
= " fast " ;
return RUN_ALL_TESTS();
}

八、注意事项

1. 不要在死亡测试里释放内存。

2. 在父进程里再次释放内存。

3. 不要在程序中使用内存堆检查。

九、总结

关于死亡测试,gtest官方的文档已经很详细了,同时在源码中也有大量的示例。如想了解更多的请参考官方的文档,或是直接看gtest源码。

简单来说,通过*_DEATH(statement, regex`)和*_EXIT( statement, predicate, regex `),我们可以非常方便的编写导致崩溃的测试案例,并且在不影响其他案例执行的情况下,对崩溃案例的结果进行检查。

系列链接:

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics