GoogleTest 使用指南 |自定义断言
GoogleTest 使用指南 |自定义断言
在某些测试场景中,内置断言可能无法满足特定需求。此时,开发者可以定义自定义断言,以实现更灵活和精准的测试验证。
test_custom_assertion.cpp:
#include "gtest/gtest.h"
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
namespace {
struct Address {
std::string city;
std::string zip_code;
};
struct UserProfile {
int id;
std::string name;
int age;
bool active;
Address address;
std::vector<std::string> roles;
};
std::string FormatRoles(const std::vector<std::string>& roles) {
std::ostringstream stream;
stream << "[";
for (std::size_t i = 0; i < roles.size(); ++i) {
if (i > 0) {
stream << ", ";
}
stream << roles[i];
}
stream << "]";
return stream.str();
}
::testing::AssertionResult UserProfileMatches(
const UserProfile& actual,
const UserProfile& expected) {
std::ostringstream failures;
if (actual.id != expected.id) {
failures << "id: expected " << expected.id << ", actual " << actual.id << "\n";
}
if (actual.name != expected.name) {
failures << "name: expected " << expected.name << ", actual " << actual.name << "\n";
}
if (actual.age != expected.age) {
failures << "age: expected " << expected.age << ", actual " << actual.age << "\n";
}
if (actual.active != expected.active) {
failures << "active: expected " << expected.active << ", actual " << actual.active << "\n";
}
if (actual.address.city != expected.address.city) {
failures << "address.city: expected " << expected.address.city
<< ", actual " << actual.address.city << "\n";
}
if (actual.address.zip_code != expected.address.zip_code) {
failures << "address.zip_code: expected " << expected.address.zip_code
<< ", actual " << actual.address.zip_code << "\n";
}
if (actual.roles != expected.roles) {
failures << "roles: expected " << FormatRoles(expected.roles)
<< ", actual " << FormatRoles(actual.roles) << "\n";
}
const std::string message = failures.str();
if (message.empty()) {
return ::testing::AssertionSuccess();
}
return ::testing::AssertionFailure() << "UserProfile mismatch:\n" << message;
}
bool Contains(const std::string& text, const std::string& expected) {
return text.find(expected) != std::string::npos;
}
} // namespace
TEST(CustomAssertionTest, VerifiesComplexObjectProperties) {
const UserProfile actual{
1001,
"Alice",
28,
true,
{"Shanghai", "200000"},
{"admin", "editor"}
};
const UserProfile expected{
1001,
"Alice",
28,
true,
{"Shanghai", "200000"},
{"admin", "editor"}
};
EXPECT_TRUE(UserProfileMatches(actual, expected));
}
TEST(CustomAssertionTest, ReportsAllMismatchedProperties) {
const UserProfile actual{
1002,
"Bob",
30,
false,
{"Beijing", "100000"},
{"viewer"}
};
const UserProfile expected{
1001,
"Alice",
28,
true,
{"Shanghai", "200000"},
{"admin", "editor"}
};
const ::testing::AssertionResult result = UserProfileMatches(actual, expected);
const std::string message = result.message();
std::cout << message;
EXPECT_FALSE(result);
EXPECT_TRUE(Contains(message, "id: expected 1001, actual 1002"));
EXPECT_TRUE(Contains(message, "name: expected Alice, actual Bob"));
EXPECT_TRUE(Contains(message, "age: expected 28, actual 30"));
EXPECT_TRUE(Contains(message, "address.city: expected Shanghai, actual Beijing"));
EXPECT_TRUE(Contains(message, "roles: expected [admin, editor], actual [viewer]"));
}
TEST(CustomAssertionTest, DISABLED_ShowsGoogleTestFailureMessage) {
const UserProfile actual{
1002,
"Bob",
30,
false,
{"Beijing", "100000"},
{"viewer"}
};
const UserProfile expected{
1001,
"Alice",
28,
true,
{"Shanghai", "200000"},
{"admin", "editor"}
};
EXPECT_TRUE(UserProfileMatches(actual, expected));
}
这个例子定义了一个复杂对象:
UserProfile {
id
name
age
active
address.city
address.zip_code
roles
}
并定义了自定义断言:
::testing::AssertionResult UserProfileMatches(
const UserProfile& actual,
const UserProfile& expected)
它会一次性检查多个属性;如果不匹配,会把所有差异都写进失败信息。
运行测试,会打印 mismatch message:

自定义断言的应用场景:
- 复杂对象验证:验证对象的多个属性是否符合预期。
- 自定义逻辑验证:根据特定业务逻辑定义断言条件。
- 增强错误信息:在断言失败时提供详细的错误信息,便于快速定位问题。

1389

被折叠的 条评论
为什么被折叠?



