C++ 期待死亡的反面是什么?

C++ 期待死亡的反面是什么?,c++,unit-testing,googletest,C++,Unit Testing,Googletest,使用google测试,让我们假设以下代码 #include <iostream> using namespace std; using MyFunc = void (*)(void); void foo_robust(MyFunc f) { if(f != nullptr) (*f)(); } void foo_not_robust(MyFunc f) { (*f)(); } void print(void) { cout << "hello worl

使用google测试,让我们假设以下代码

#include <iostream>

using namespace std;
using MyFunc = void (*)(void);

void foo_robust(MyFunc f)   { if(f != nullptr) (*f)(); }
void foo_not_robust(MyFunc f)   { (*f)(); }
void print(void)     { cout << "hello world" << endl; }

int main()
{
    foo(&print); //works
    foo(nullptr); //runtime error ?
    return 0;
}
我想做:

TEST(TestAssertDeath, No_Death)
{
    EXPECT_NO_DEATH(foo(&print)); //will return OK, because does not die.
    EXPECT_NO_DEATH(foo(nullptr)); // will return OK, if foo is robust, FAILED or DEATH otherwise (UB: it might even return OK)
}
TEST(TestAssertDeath, No_Death)
{
    EXPECT_NO_FATAL_FAILURE(foo(&print)); //will return OK, because does not die.
    EXPECT_NO_FATAL_FAILURE(foo(nullptr)); // will crash (UB: might even return OK)
}
是否有任何谷歌宏“期待死亡”的工作? 我试着期待没有致命的失败,但它崩溃了,好像我什么都没放。 我想做:

TEST(TestAssertDeath, No_Death)
{
    EXPECT_NO_DEATH(foo(&print)); //will return OK, because does not die.
    EXPECT_NO_DEATH(foo(nullptr)); // will return OK, if foo is robust, FAILED or DEATH otherwise (UB: it might even return OK)
}
TEST(TestAssertDeath, No_Death)
{
    EXPECT_NO_FATAL_FAILURE(foo(&print)); //will return OK, because does not die.
    EXPECT_NO_FATAL_FAILURE(foo(nullptr)); // will crash (UB: might even return OK)
}
但我不想让考试停止

谷歌测试目前给了我以下错误

[ RUN      ] MyClass.MyUnitTestA
[      OK  ]
[ RUN      ] MyClass.MyUnitTestB
[      OK  ]
[ RUN      ] MyClass.MyUnitTestC
mingw32-make[3]: *** [CMakeFiles/myproject-coverage] Error -1073741819
mingw32-make[2]: *** [CMakeFiles/myproject-coverage.dir/all] Error 2
mingw32-make[1]: *** [CMakeFiles/myproject-coverage.dir/rule] Error 2
mingw32-make: *** [myproject-coverage] Error 2
因为这会停止其他测试的运行,如果代码不健壮,我希望如下所示

[ RUN      ] MyClass.MyUnitTestA
[      OK  ]
[ RUN      ] MyClass.MyUnitTestB
[      OK  ]
[ RUN      ] MyClass.MyUnitTestC
[  DEATH   ] or [  FAILED  ]
[ RUN      ] MyClass.MyUnitTestD
[      OK  ]
如果代码是健壮的:

[ RUN      ] MyClass.MyUnitTestA
[      OK  ]
[ RUN      ] MyClass.MyUnitTestB
[      OK  ]
[ RUN      ] MyClass.MyUnitTestC
[      OK  ]
[ RUN      ] MyClass.MyUnitTestD
[      OK  ]

重要提示:我知道行foo_not_robust(nullptr)是UB,不会自动崩溃,但如果是这样,我希望跳过这一行并将其标记为失败。

要使单元测试对崩溃具有鲁棒性,可以尝试在子进程中运行每个测试,父进程监视子进程的成功、失败或崩溃

但是有一个简单的方法,事实上你可以做一些事情,比如期待死亡

从google测试文档:

TEST(mydeath测试,NormalExit){
预期退出(NormalExit(),::测试::退出代码(0),“成功”);
}

您可以使用两条语句
(statement1,statement2)
statement1=statement
以及
statement2=exit(0)

它提供了以下两个自定义宏:

# define EXPECT_CRASH(statement) \
    EXPECT_EXIT((statement,exit(0)),::testing::KilledBySignal(SIGSEGV),".*")
EXPECT\u CRASH()
相当于
EXPECT\u DEATH()

EXPECT\u NO\u CRASH()
相当于请求的
EXPECT\u NO\u DEATH()

请注意,
::testing::KilledBySignal(信号号)
在Windows上不可用。 作为Windows的解决方案,您可以做的只是定义:

# define EXPECT_CRASH(statement) \
    EXPECT_DEATH(statement,".*")
给出以下消息:

[ RUN      ] MyClass.MyUnitTestA
[      OK  ]
[ RUN      ] MyClass.MyUnitTestB
[      OK  ]
[ RUN      ] MyClass.MyUnitTestC
Death test: (foo(),exit(0))
    Result: died but not with expected exit code:
            Exited with exit status -1073741819
Actual msg:
[  DEATH   ]
[ RUN      ] MyClass.MyUnitTestD
[      OK  ]

为了使单元测试对崩溃具有健壮性,您可以尝试在子进程中运行每个测试,并使用父进程监视子进程的成功、失败或崩溃

但是有一个简单的方法,事实上你可以做一些事情,比如期待死亡

从google测试文档:

TEST(mydeath测试,NormalExit){
预期退出(NormalExit(),::测试::退出代码(0),“成功”);
}

您可以使用两条语句
(statement1,statement2)
statement1=statement
以及
statement2=exit(0)

它提供了以下两个自定义宏:

# define EXPECT_CRASH(statement) \
    EXPECT_EXIT((statement,exit(0)),::testing::KilledBySignal(SIGSEGV),".*")
EXPECT\u CRASH()
相当于
EXPECT\u DEATH()

EXPECT\u NO\u CRASH()
相当于请求的
EXPECT\u NO\u DEATH()

请注意,
::testing::KilledBySignal(信号号)
在Windows上不可用。 作为Windows的解决方案,您可以做的只是定义:

# define EXPECT_CRASH(statement) \
    EXPECT_DEATH(statement,".*")
给出以下消息:

[ RUN      ] MyClass.MyUnitTestA
[      OK  ]
[ RUN      ] MyClass.MyUnitTestB
[      OK  ]
[ RUN      ] MyClass.MyUnitTestC
Death test: (foo(),exit(0))
    Result: died but not with expected exit code:
            Exited with exit status -1073741819
Actual msg:
[  DEATH   ]
[ RUN      ] MyClass.MyUnitTestD
[      OK  ]

你为什么认为你需要这个?当您出现运行时错误时,您的测试将无法通过,无需为此做额外的操作。从某种意义上说,你总是有一个隐含的
EXPECT\u NO\u DEATH
对UB进行这样的测试是个坏主意。(因为我似乎找不到这篇文章)如果测试不通过,我就没有完整的活动结果,这就是我想要的。我想确保我正在测试的模块对nullptr
EXPECT_DEATH
的鲁棒性仅限于此。。。期待崩溃或错误。您应该只在希望线路崩溃时使用它,或者在您实际期望线路崩溃时使用它。当你真的希望它通过并对你的情况“健壮”时,以这种方式使用它假设失败。你为什么认为你需要它?当您出现运行时错误时,您的测试将无法通过,无需为此做额外的操作。从某种意义上说,你总是有一个隐含的
EXPECT\u NO\u DEATH
对UB进行这样的测试是个坏主意。(因为我似乎找不到这篇文章)如果测试不通过,我就没有完整的活动结果,这就是我想要的。我想确保我正在测试的模块对nullptr
EXPECT_DEATH
的鲁棒性仅限于此。。。期待崩溃或错误。您应该只在希望线路崩溃时使用它,或者在您实际期望线路崩溃时使用它。以这种方式使用它会假设失败,而实际上您希望它能够通过并针对您的条件“健壮”。