c++ - 使用 void 函数检查 gtest 中的错误
问题描述
在 gtest 中使用使用 ASSERT_ 或 EXPECT_ 宏的辅助函数时,该辅助函数必须为无效。但是,我也想在调用测试代码中检查这些错误。
有一个 ASSERT_NO_FATAL_FAILURE 宏有助于在触发 ASSERT_ 的情况下停止调用代码,但我想通过正确处理 EXPECT_ 故障(阅读:NonFatalFailures)来扩展它。这是我到目前为止得到的:
#include <gtest/gtest.h>
// A void test-function using ASSERT_ or EXPECT_ calls should be encapsulated by this macro.
// Example: CHECK_FOR_FAILURES(MyCheckForEquality(lhs, rhs))
#define CHECK_FOR_FAILURES(statement) \
ASSERT_NO_FATAL_FAILURE((statement)); \
EXPECT_FALSE(HasNonfatalFailure())
void TestHelperFunction(bool givenAssert, int givenExpect)
{
ASSERT_TRUE(givenAssert); // note: this is line 11 in my code
EXPECT_EQ(givenExpect, 0); // note: this is line 12 in my code
}
TEST(FailureInFunctionTestNoChecks, noChecks)
{
// note: this is line 17 in my code
TestHelperFunction(true, 0);
TestHelperFunction(true, 1);
for (int i = 0; i < 3; ++i)
{
TestHelperFunction(true, i);
}
TestHelperFunction(false, 1);
TestHelperFunction(true, 2);
}
TEST(FailureInFunctionTestWithChecks, withChecks)
{
// note: this is line 30 in my code
CHECK_FOR_FAILURES(TestHelperFunction(true, 0)) << "\n All good - will NOT be seen! \n";
CHECK_FOR_FAILURES(TestHelperFunction(true, 1)) << "\n optional msg: First Expect failed \n";
for (int i = 0; i < 3; ++i)
{
CHECK_FOR_FAILURES(TestHelperFunction(true, i)) << "\n optional msg: Expect failed for i=" << i << "\n";
}
CHECK_FOR_FAILURES(TestHelperFunction(false, 1)) << "this message will NOT be seen due to the assert";
CHECK_FOR_FAILURES(TestHelperFunction(true, 2)) << "\n will not be seen because assert stops the test \n";
}
// This test creates the following output:
// Note: Google Test filter = *FailureInFunctionTest*
// [==========] Running 2 tests from 2 test cases.
// [----------] Global test environment set-up.
// [----------] 1 test from FailureInFunctionTestNoChecks
// [ RUN ] FailureInFunctionTestNoChecks.noChecks
// ./checked_test_failure.cpp:12: Failure
// Expected equality of these values:
// givenExpect
// Which is: 1
// 0
// ./checked_test_failure.cpp:12: Failure
// Expected equality of these values:
// givenExpect
// Which is: 1
// 0
// ./checked_test_failure.cpp:12: Failure
// Expected equality of these values:
// givenExpect
// Which is: 2
// 0
// ./checked_test_failure.cpp:11: Failure
// Value of: givenAssert
// Actual: false
// Expected: true
// ./checked_test_failure.cpp:12: Failure
// Expected equality of these values:
// givenExpect
// Which is: 2
// 0
// [ FAILED ] FailureInFunctionTestNoChecks.noChecks (0 ms)
// [----------] 1 test from FailureInFunctionTestNoChecks (0 ms total)
//
// [----------] 1 test from FailureInFunctionTestWithChecks
// [ RUN ] FailureInFunctionTestWithChecks.withChecks
// ./checked_test_failure.cpp:12: Failure
// Expected equality of these values:
// givenExpect
// Which is: 1
// 0
// ./checked_test_failure.cpp:32: Failure
// Value of: HasNonfatalFailure()
// Actual: true
// Expected: false
//
// optional msg: First Expect failed
//
// ./checked_test_failure.cpp:35: Failure
// Value of: HasNonfatalFailure()
// Actual: true
// Expected: false
//
// optional msg: Expect failed for i=0
//
// ./checked_test_failure.cpp:12: Failure
// Expected equality of these values:
// givenExpect
// Which is: 1
// 0
// ./checked_test_failure.cpp:35: Failure
// Value of: HasNonfatalFailure()
// Actual: true
// Expected: false
//
// optional msg: Expect failed for i=1
//
// ./checked_test_failure.cpp:12: Failure
// Expected equality of these values:
// givenExpect
// Which is: 2
// 0
// ./checked_test_failure.cpp:35: Failure
// Value of: HasNonfatalFailure()
// Actual: true
// Expected: false
//
// optional msg: Expect failed for i=2
//
// ./checked_test_failure.cpp:11: Failure
// Value of: givenAssert
// Actual: false
// Expected: true
// ./checked_test_failure.cpp:37: Failure
// Expected: (TestHelperFunction(false, 1)) doesn't generate new fatal failures in the current thread.
// Actual: it does.
// [ FAILED ] FailureInFunctionTestWithChecks.withChecks (1 ms)
// [----------] 1 test from FailureInFunctionTestWithChecks (1 ms total)
//
// [----------] Global test environment tear-down
// [==========] 2 tests from 2 test cases ran. (1 ms total)
// [ PASSED ] 0 tests.
// [ FAILED ] 2 tests, listed below:
// [ FAILED ] FailureInFunctionTestNoChecks.noChecks
// [ FAILED ] FailureInFunctionTestWithChecks.withChecks
//
// 2 FAILED TESTS
//
正如您从输出中看到的:使用新的“CHECK_FOR_FAILURES”宏改进了测试输出:它告诉您哪一行导致了失败,并在断言被命中后阻止执行测试。
但是,使用“HasNonfatalFailure()”还不够好,正如您在 i=0 的输出中看到的那样。原因是已经存在非致命错误,对于 i=0 没有新的非致命错误,但 HasNonfatalFailure() 由于旧错误而返回 true .. :-(
知道如何摆脱错误的 i=0 输出吗?
解决方案
使用gtest 文档的建议的一种明显方法如下,但我宁愿在没有自定义消息或 SCOPED_TRACE() 宏的情况下这样做
#include <gtest/gtest.h>
// A void test-function using ASSERT_ or EXPECT_ calls with a custom message should be encapsulated
// by this macro. Example: CHECK_FOR_FAILURES_MSG(MyCheckForEquality(counter, 42), "for counter=42")
#define CHECK_FOR_FAILURES_MSG(statement, message) \
{ \
SCOPED_TRACE(message); \
ASSERT_NO_FATAL_FAILURE((statement)); \
}
// A void test-function using ASSERT_ or EXPECT_ calls should be encapsulated by this macro.
// Example: CHECK_FOR_FAILURES(MyCheckForEquality(lhs, rhs))
#define CHECK_FOR_FAILURES(statement) CHECK_FOR_FAILURES_MSG(statement, " <-- line of failure\n")
void TestHelperFunction(bool givenAssert, int givenExpect)
{
ASSERT_TRUE(givenAssert); // note: this is line 17 in my code
EXPECT_EQ(givenExpect, 0); // note: this is line 18 in my code
}
TEST(FailureInFunctionTestNoChecks, noChecks)
{
// note: this is line 23 in my code
TestHelperFunction(true, 0);
TestHelperFunction(true, 1);
for (int i = 0; i < 3; ++i)
{
TestHelperFunction(true, i);
}
TestHelperFunction(false, 1);
TestHelperFunction(true, 2);
}
TEST(FailureInFunctionTestWithChecks, withChecks)
{
// note: this is line 36 in my code
CHECK_FOR_FAILURES(TestHelperFunction(true, 0));
CHECK_FOR_FAILURES(TestHelperFunction(true, 1));
for (int i = 0; i < 3; ++i)
{
CHECK_FOR_FAILURES_MSG(TestHelperFunction(true, i), "for i=" + std::to_string(i) + "\n");
}
CHECK_FOR_FAILURES(TestHelperFunction(false, 1));
CHECK_FOR_FAILURES(TestHelperFunction(true, 2));
}
// Note: Google Test filter = *FailureInFunction*
//[==========] Running 2 tests from 2 test cases.
//[----------] Global test environment set-up.
//[----------] 1 test from FailureInFunctionTestNoChecks
//[ RUN ] FailureInFunctionTestNoChecks.noChecks
//./checked_test_failure.cpp:18: Failure
//Expected equality of these values:
// givenExpect
// Which is: 1
// 0
//./checked_test_failure.cpp:18: Failure
//Expected equality of these values:
// givenExpect
// Which is: 1
// 0
//./checked_test_failure.cpp:18: Failure
//Expected equality of these values:
// givenExpect
// Which is: 2
// 0
//./checked_test_failure.cpp:17: Failure
//Value of: givenAssert
// Actual: false
//Expected: true
//./checked_test_failure.cpp:18: Failure
//Expected equality of these values:
// givenExpect
// Which is: 2
// 0
//[ FAILED ] FailureInFunctionTestNoChecks.noChecks (0 ms)
//[----------] 1 test from FailureInFunctionTestNoChecks (0 ms total)
//
//[----------] 1 test from FailureInFunctionTestWithChecks
//[ RUN ] FailureInFunctionTestWithChecks.withChecks
//./checked_test_failure.cpp:18: Failure
//Expected equality of these values:
// givenExpect
// Which is: 1
// 0
//Google Test trace:
//./checked_test_failure.cpp:38: <-- line of failure
//
//./checked_test_failure.cpp:18: Failure
//Expected equality of these values:
// givenExpect
// Which is: 1
// 0
//Google Test trace:
//./checked_test_failure.cpp:41: for i=1
//
//./checked_test_failure.cpp:18: Failure
//Expected equality of these values:
// givenExpect
// Which is: 2
// 0
//Google Test trace:
//./checked_test_failure.cpp:41: for i=2
//
//./checked_test_failure.cpp:17: Failure
//Value of: givenAssert
// Actual: false
//Expected: true
//Google Test trace:
//./checked_test_failure.cpp:43: <-- line of failure
//
//./checked_test_failure.cpp:43: Failure
//Expected: (TestHelperFunction(false, 1)) doesn't generate new fatal failures in the current thread.
// Actual: it does.
//Google Test trace:
//./checked_test_failure.cpp:43: <-- line of failure
//
//[ FAILED ] FailureInFunctionTestWithChecks.withChecks (0 ms)
//[----------] 1 test from FailureInFunctionTestWithChecks (0 ms total)
//
//[----------] Global test environment tear-down
//[==========] 2 tests from 2 test cases ran. (0 ms total)
//[ PASSED ] 0 tests.
//[ FAILED ] 2 tests, listed below:
//[ FAILED ] FailureInFunctionTestNoChecks.noChecks
//[ FAILED ] FailureInFunctionTestWithChecks.withChecks
//
// 2 FAILED TESTS
//
推荐阅读
- sum - 将平方数相加的C程序 - 不起作用
- django - Django Annotate - 获取不同字段值的列表
- python - Python3 使用 os.popen 在 osx 上执行命令给了我一个奇怪的异常
- html - 单击链接时使用悬停打开下拉菜单并关闭菜单
- visual-c++ - Visual Studio 2017/Windows 2012 上的错误 - MFC 不支持小于 0x0501 的 WINVER
- r - 使用 SparkR 的逐行计算
- javascript - Azure b2c 忘记密码链接有时会重定向回登录
- mercurial - “路径以目录分隔符结尾”是什么意思以及如何解决它?
- c# - 为什么某些证书的 Request.ClientCertificate 为空,而其他证书则为空?
- python - Python tkinter-删除选定的列表框项目