C ++ Google test (gtest):如何创建自定义断言和期望?

c++ Google test (gtest): how to create custom asserts and expects?

本文关键字:自定义 创建 断言 期望 Google test gtest 何创建      更新时间:2023-10-16

我正在使用gtest为我的c ++程序创建单元测试。在我的测试中,我必须编写很多这样的检查:

ASSERT_TRUE(myObject.IsValid());
EXPECT_EQ(myObject.GetSomeAttribute(), expectedValue);

我必须编写两个检查,因为如果我省略ASSERT_TRUE并且myObject恰好无效,那么myObject.GetSomeAttributre()呼叫就会崩溃。即使在测试中也不好。

我想要的是写这样的东西:

EXPECT_XXX_EQ(myObject.GetSomeAttribute(), expectedValue);

这行代码应该与原来的两行大致相同(可选奖励,如果myObject无效,这将被报告,GetSomeAttribute()不会被调用,但测试将继续运行(。

如何编写这样的自定义断言/期望?

从高级指南中,我们可以看到有几种方法可以做到这一点。

最简单的方法是在子例程中使用断言:

template<typename T>
void AssertAttributeEquals(MyObject const& obj, T value) {
ASSERT_TRUE(obj.IsValid());
// googletest has the assumption that you put the
// expected value first
EXPECT_EQ(value, obj.GetAttribute());
}

你可以这样称呼它:

AssertAttributeEquals(myObject, expectedValue);

尽管您可能希望使用SCOPED_TRACE在失败时获得更好的消息:

{
SCOPED_TRACE("whatever message you want");
AssertAttributeEquals(myObject, expectedValue);
}

或者,您可以使用返回AssertionResult的函数:

template<typename T>
::testing::AssertionResult AttributeEquals(MyObject const& obj, T value) {
if (!obj.IsValid()) {
// If MyObject is streamable, then we probably want to include it
// in the error message.
return ::testing::AssertionFailure() << obj << " is not valid";
}
auto attr = obj.GetAttribute();
if (attr == value) {
return ::testing::AssertionSuccess();
} else {
return ::testing::AssertionFailure() << attr << " not equal to " << value;
}
}

这可以像这样使用:

EXPECT_TRUE(AttributeEquals(myObject, expectedValue));

第二种技术的好处是即使您不使用SCOPED_TRACE也能生成漂亮的错误消息

我可以消除使用宏复制所有对SCOPED_TRACE("...")调用的需要。现在,您可以在 void 函数中使用正常的 GTEST 断言,并在测试中使用该宏:

test_common.h:

inline void AssertTokenTypesEqual__(const std::string& code, std::vector<TokenType> expectedTokens)
{
auto tokens = Tokenize(code);
ASSERT_EQ(tokens.size(), expectedTokens.size());
for (int i = 0; i < tokens.size(); ++i) {
ASSERT_EQ(expectedTokens[i], tokens[i].type);
}
}
#define ASSERT_TOKEN_TYPES_EQUAL(code__, expectedTokens__)  
SCOPED_TRACE("Tokenization didn't match expectations"); 
AssertTokenTypesEqual__(code__, expectedTokens__)

我的测试.cpp:

TEST(TokenizerTest, Works) {
auto code = "void func();";
auto expectedTokens = {...}; // <- you might need to create variables of your values outside the assertion.
ASSERT_TOKEN_TYPES_EQUAL(code, expectedTokens);
}