写死亡测试来验证std :: set_terminate行为

Nic*_*aus 6 c++ exception-handling exception googletest c++11

我正在使用gtest为异常处理代码编写一些单元测试.举一个简单的例子,假设我想让我的程序abort处理任何未处理的异常,所以我创建了以下测试:

TEST_F(myFixture, myTest)
{
    std::set_terminate([](){std::abort(); });

    EXPECT_DEATH(throw std::runtime_error("terminate"), ".*");
}
Run Code Online (Sandbox Code Playgroud)

我希望这会成功,因为abort应该在程序上调用.但是,我的实际结果是:

错误:死亡测试:抛出std :: runtime_error("终止")

结果:抛出异常.
错误消息:

[
死] [死] main.cpp(122)::捕获std :: exception-derived异常转义死亡测试语句.异常消息:终止

[死亡]

我认为gtest的异常处理程序正在阻碍.我已经尝试使用GTEST_CATCH_EXCEPTIONS环境变量和高级指南中--gtest_catch_exceptions=0提到的命令行标志禁用它们,但我得到了相同的结果.

我做错了什么,或者是"异常死亡"而不是gtest可以测试的东西?

Mik*_*han 6

我做错了什么,或者是"异常死亡"而不是gtest可以测试的东西?

你所做的是错的,因为 "异常死亡"不是gtest可以测试的.

EXPECT_DEATH(statement, regex);
Run Code Online (Sandbox Code Playgroud)

验证statement调用abortexit导致输出匹配 regex.该声明throw std::runtime_error("terminate")不会调用, abort或者exit可以从程序中捕获任何异常的可能性中看出并让它继续存在.如果未捕获异常,则运行时库将调用terminate,以这种或那种方式结束程序.但是这个结果并不是由任何throw声明决定的.

参见死亡测试文件,特别是:

...任何以预期的方式检查程序终止(除了抛出异常)的测试也是死亡测试.

请注意,如果一段代码抛出异常,我们不认为它是死亡测试的"死亡",因为代码的调用者可以捕获异常并避免崩溃.如果要验证代码抛出的异常,请参阅异常断言.

和:

请注意,死亡测试只涉及三件事:

  1. 声明是否中止或退出流程?...

我感谢你可能在这里过度监控你的真实问题,但是你几乎不需要测试未处理的异常将导致terminate 被调用,或者terminate将调用有效的终止处理程序,除非你的艰巨任务是测试你的编译器和标准的实现图书馆.也许应该播出更多真正的问题?

后来

我的问题是我的程序没有(或不应该)继续.它应该通过终止处理程序中止.

它应该,但根据文档,您的程序不应该进行的期望不会 EXPECT_DEATH 在任何 throw 语句进行测试,因为没有throw语句终止程序.

我真正想测试的是我的set_terminate处理程序的行为是正确的.

set_terminate只有在设置了该处理程序,调用std::terminate()具有您期望的结果时,处理程序的行为才是正确的.这个问题独立于任何throw陈述,你可以测试它:

#include <iostream>
#include <gtest/gtest.h>
#include <exception>


TEST(the_end, is_nigh)
{
    std::set_terminate([](){std::cout << "Goodbye cruel world\n", std::abort(); });

    EXPECT_DEATH(std::terminate(), ".*");
}
int main(int argc, char **argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
Run Code Online (Sandbox Code Playgroud)

产生:

[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from the_end
[ RUN      ] the_end.is_nigh
Goodbye cruel world
[       OK ] the_end.is_nigh (172 ms)
[----------] 1 test from the_end (172 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (172 ms total)
[  PASSED  ] 1 test.
Run Code Online (Sandbox Code Playgroud)