如何使用 google mock 对自定义结构的矢量对象的内容进行单元测试和检查?
How do I unit test and check the contents of a vector object of a custom struct using google mock?
如果结构是
struct Point{
double x;
double y;
};
并且一个函数的输出是vector<Point>
并且大小为10,我怎么写一个Google测试或者Google模拟(我觉得这个更适合this) 来验证向量的内容?我可以在原始字符串中写入预期的输出。
首先:手写断言并逐个检查元素的大小和内容是可以的:
std::vector<Point> MethodReturningVector();
TEST(MethodReturningVectorTest, CheckSizeAndFirstElementTest) {
const auto result = MethodReturningVector();
ASSERT_EQ(10, result.size());
ASSERT_NEAR(42.f, result[0].x, 0.001f);
ASSERT_NEAR(3.141592.f, result[0].y, 0.001f);
}
一旦你写了很多不同的测试,你就会看到断言的共同模式,然后你可以重构你的测试,一切都会自然而然地发生。
但是正如您提到的 GMock,确实有一些 GMock 技术可以使用。有 in-built 匹配器来匹配 STL-like 数组(我说 STL-like 因为只需要开始和结束),例如ElementsAre
(ElementsAreArray
也存在)。但是,它们要求数组中的元素可以进行比较。这反过来要求为您的类型定义 operator==
(很少),因为默认的 Eq
匹配器正在使用它。您可以使用另一个 in-built 匹配器为自定义类型定义自己的匹配器,例如 AllOf
(匹配器的聚合器)和 Field
(匹配结构的给定字段)。匹配器可以合并。完整图片见 (working example):
struct Point{
double x;
double y;
};
std::vector<Point> MethodReturningVector() {
std::vector<Point> result(3);
result[0] = Point{42.f, 3.141592f};
return result;
}
MATCHER_P(Near, expected, "...") {
constexpr auto allowed_diff = 0.001f; // allow small diference
if (!(expected - arg <= allowed_diff && arg <= expected + allowed_diff)) {
*result_listener << "expected: " << expected << ", actual: " << arg;
return false;
}
return true;
}
auto MatchPoint(Point p) {
return testing::AllOf(testing::Field(&Point::x, Near(p.x)),
testing::Field(&Point::y, Near(p.y)));
}
TEST(MethodReturningVectorTest, TestOneElement)
{
const auto result = MethodReturningVector();
ASSERT_EQ(result.size(), 3);
ASSERT_THAT(result[0], MatchPoint(Point{42.f, 3.1415}));
}
TEST(MethodReturningVectorTest, TestWholeArray)
{
const auto result = MethodReturningVector();
ASSERT_THAT(result, testing::ElementsAre(
MatchPoint(Point{42.f, 3.1415f}),
MatchPoint(Point{0.f, 0.f}),
MatchPoint(Point{0.f, 0.f})));
}
我强烈建议您从 GTest/GMock 食谱等着手
如果结构是
struct Point{
double x;
double y;
};
并且一个函数的输出是vector<Point>
并且大小为10,我怎么写一个Google测试或者Google模拟(我觉得这个更适合this) 来验证向量的内容?我可以在原始字符串中写入预期的输出。
首先:手写断言并逐个检查元素的大小和内容是可以的:
std::vector<Point> MethodReturningVector();
TEST(MethodReturningVectorTest, CheckSizeAndFirstElementTest) {
const auto result = MethodReturningVector();
ASSERT_EQ(10, result.size());
ASSERT_NEAR(42.f, result[0].x, 0.001f);
ASSERT_NEAR(3.141592.f, result[0].y, 0.001f);
}
一旦你写了很多不同的测试,你就会看到断言的共同模式,然后你可以重构你的测试,一切都会自然而然地发生。
但是正如您提到的 GMock,确实有一些 GMock 技术可以使用。有 in-built 匹配器来匹配 STL-like 数组(我说 STL-like 因为只需要开始和结束),例如ElementsAre
(ElementsAreArray
也存在)。但是,它们要求数组中的元素可以进行比较。这反过来要求为您的类型定义 operator==
(很少),因为默认的 Eq
匹配器正在使用它。您可以使用另一个 in-built 匹配器为自定义类型定义自己的匹配器,例如 AllOf
(匹配器的聚合器)和 Field
(匹配结构的给定字段)。匹配器可以合并。完整图片见 (working example):
struct Point{
double x;
double y;
};
std::vector<Point> MethodReturningVector() {
std::vector<Point> result(3);
result[0] = Point{42.f, 3.141592f};
return result;
}
MATCHER_P(Near, expected, "...") {
constexpr auto allowed_diff = 0.001f; // allow small diference
if (!(expected - arg <= allowed_diff && arg <= expected + allowed_diff)) {
*result_listener << "expected: " << expected << ", actual: " << arg;
return false;
}
return true;
}
auto MatchPoint(Point p) {
return testing::AllOf(testing::Field(&Point::x, Near(p.x)),
testing::Field(&Point::y, Near(p.y)));
}
TEST(MethodReturningVectorTest, TestOneElement)
{
const auto result = MethodReturningVector();
ASSERT_EQ(result.size(), 3);
ASSERT_THAT(result[0], MatchPoint(Point{42.f, 3.1415}));
}
TEST(MethodReturningVectorTest, TestWholeArray)
{
const auto result = MethodReturningVector();
ASSERT_THAT(result, testing::ElementsAre(
MatchPoint(Point{42.f, 3.1415f}),
MatchPoint(Point{0.f, 0.f}),
MatchPoint(Point{0.f, 0.f})));
}
我强烈建议您从 GTest/GMock 食谱等着手