【问题标题】:write death test to verify std::set_terminate behavior编写死亡测试来验证 std::set_terminate 行为
【发布时间】:2016-08-30 18:57:26
【问题描述】:

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

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

    EXPECT_DEATH(throw std::runtime_error("terminate"), ".*");
}

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

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

结果:抛出异常。
错误信息:

[死亡]
[ DEATH ] main.cpp(122):: Caught std::exception-derived 异常转义 死亡测试声明。异常消息:终止

[死亡]

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

我做错了什么,还是“异常死亡”不是 gtest 可以测试的?

【问题讨论】:

    标签: c++ c++11 exception exception-handling googletest


    【解决方案1】:

    我做错了什么,还是“异常死亡”不是 gtest 可以测试的?

    你的做法是错误的,因为“异常死亡”不是 gtest 可以测试的。

    EXPECT_DEATH(statement, regex);
    

    验证statement 调用abortexit 并导致输出匹配 regex。声明throw std::runtime_error("terminate") 不调用 abortexit,从捕获程序中的任何异常并让它继续运行的可能性可以看出。 如果没有捕获到异常,那么运行时库将调用terminate,以一种或另一种方式结束程序。但是这个结果不是由任何throw 语句决定的。

    documentation of death-tests, 特别是:

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

    请注意,如果一段代码抛出异常,我们不会将其视为“死亡” 出于死亡测试的目的,因为代码的调用者可以捕获 异常并避免崩溃。如果你想验证你的抛出的异常 代码,请参阅异常断言。

    和:

    请注意,死亡测试只关心三件事:

    1. 语句是中止还是退出进程? ...

    我很欣赏你在这里可能过于简单化了你的真正问题,但你 几乎不需要测试未处理的异常会导致terminate 被调用,或者terminate 将调用操作终止- 处理程序,除非您有艰巨的职责来测试 你的编译器和标准库。也许更多真正的问题应该 播出了吗?

    稍后

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

    应该,但根据文档,您的程序应该 not carry on 不被EXPECT_DEATH测试throw语句,因为没有throw语句终止程序。 p>

    我真正想测试的是我的 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();
    }
    

    产生:

    [==========] 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.
    

    【讨论】:

    • 我真正想要测试的是我的set_terminate 处理程序的行为是否正确,并且在我认为应该正确时调用它。在实际程序中,它在最终调用 abort 之前做了几件事(生成时间戳/堆栈跟踪)。
    • “从捕获程序中的任何异常并让它继续运行的可能性可以看出”......我的问题是我的程序不(或不应该)继续.它应该通过终止处理程序abort
    • @NicolasHolthaus 更新了。
    猜你喜欢
    • 1970-01-01
    • 2014-09-13
    • 2021-08-24
    • 2015-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-12
    相关资源
    最近更新 更多