GTest 中的嵌套匹配器
Nested Matchers in GTest
我想在其他匹配器中使用一些现有的匹配器。我知道 MatcherInterface 解决方案,但我想知道我是否可以使用 MATCHER_P
定义的匹配器。如果找到这个解决方案:
struct Foo
{
double x;
double y;
};
struct Bar
{
Foo foo;
int i;
};
MATCHER_P(EqFoo, foo, "")
{
::testing::Matcher<double> x_matcher = ::testing::DoubleNear(foo.x, 0.0001);
if (!x_matcher.MatchAndExplain(arg.x, result_listener))
{
return false;
}
::testing::Matcher<double> y_matcher = ::testing::DoubleNear(foo.y, 0.0001);
if (!y_matcher.MatchAndExplain(arg.y, result_listener))
{
return false;
}
return true;
}
MATCHER_P(EqBar, bar, "")
{
::testing::Matcher<Foo> foo_matcher = EqFooMatcherP<Foo>(bar.foo);
if (!foo_matcher.MatchAndExplain(arg.foo, result_listener))
{
return false;
}
if (bar.i != arg.i)
{
return false;
}
return true;
}
TEST_F(TestClass, BarTest)
{
Bar bar_val{{10.12, 76.43}, 78};
Bar bar_exp{{10.12, 99.99}, 78};
EXPECT_THAT(bar_val, EqBar(bar_exp));
}
我只是想知道,有没有更好更好的解决方案
- 在另一个中使用我自己的 MATCHER_P 匹配器
- 在另一个中使用原始 GTest 匹配器。
正确的方法是尽可能使用gtest/gmock中的匹配器。仅当没有已提供的匹配器时 - 使用您自己的匹配器。
在您的示例中 - 就像这样简单:
auto EqFoo(const Foo& expected)
{
return ::testing::AllOf(
::testing::Field(&Foo::x, ::testing::DoubleNear(expected.x, 0.0001)),
::testing::Field(&Foo::y, ::testing::DoubleNear(expected.y, 0.0001))
);
}
auto EqBar(const Bar& expected)
{
return ::testing::AllOf(
::testing::Field(&Bar::foo, EqFoo(expected.foo)),
::testing::Field(&Bar::i, expected.i)
);
}
更通用的方法是使用重载:
auto MatchDouble(double expected)
{
return ::testing::DoubleNear(expected.x, 0.0001);
}
auto MatchFoo(::testing::Matcher<double> x, ::testing::Matcher<double> y)
{
return ::testing::AllOf(
::testing::Field(&Foo::x, x),
::testing::Field(&Foo::y, y)
);
}
auto MatchFoo(double x, double y)
{
return MatchFoo(MatchDouble(x), MatchDouble(y));
}
auto MatchBar(::testing::Matcher<Foo> foo, ::testing::Matcher<int> i)
{
return ::testing::AllOf(
::testing::Field(&Bar::foo, foo),
::testing::Field(&Bar::i, expected.i),
);
}
auto MatchBar(const Bar& expected)
{
return MatchBar(expected.foo, expected.i);
}
所以你的测试:
TEST_F(TestClass, BarTest)
{
Bar bar_val{{10.12, 76.43}, 78};
Bar bar_exp{{10.12, 99.99}, 78};
EXPECT_THAT(bar_val, MatchBar(bar_exp));
// or - e.g. you can match only Bar::y if other things are irrelevant in your test
EXPECT_THAT(bar_val, MatchBar(MatchFoo(_, MatchDouble(2.001)), _);
}
无论如何 - 使用 MATCHER_P
应该是相当罕见的情况,我自己的观察是这个宏确实被过度使用了。
如果您的项目是 pre-C++14 - 使用 ::testing::Matcher<T>
而不是 auto
作为所有这些函数的 return 类型。
我想在其他匹配器中使用一些现有的匹配器。我知道 MatcherInterface 解决方案,但我想知道我是否可以使用 MATCHER_P
定义的匹配器。如果找到这个解决方案:
struct Foo
{
double x;
double y;
};
struct Bar
{
Foo foo;
int i;
};
MATCHER_P(EqFoo, foo, "")
{
::testing::Matcher<double> x_matcher = ::testing::DoubleNear(foo.x, 0.0001);
if (!x_matcher.MatchAndExplain(arg.x, result_listener))
{
return false;
}
::testing::Matcher<double> y_matcher = ::testing::DoubleNear(foo.y, 0.0001);
if (!y_matcher.MatchAndExplain(arg.y, result_listener))
{
return false;
}
return true;
}
MATCHER_P(EqBar, bar, "")
{
::testing::Matcher<Foo> foo_matcher = EqFooMatcherP<Foo>(bar.foo);
if (!foo_matcher.MatchAndExplain(arg.foo, result_listener))
{
return false;
}
if (bar.i != arg.i)
{
return false;
}
return true;
}
TEST_F(TestClass, BarTest)
{
Bar bar_val{{10.12, 76.43}, 78};
Bar bar_exp{{10.12, 99.99}, 78};
EXPECT_THAT(bar_val, EqBar(bar_exp));
}
我只是想知道,有没有更好更好的解决方案
- 在另一个中使用我自己的 MATCHER_P 匹配器
- 在另一个中使用原始 GTest 匹配器。
正确的方法是尽可能使用gtest/gmock中的匹配器。仅当没有已提供的匹配器时 - 使用您自己的匹配器。
在您的示例中 - 就像这样简单:
auto EqFoo(const Foo& expected)
{
return ::testing::AllOf(
::testing::Field(&Foo::x, ::testing::DoubleNear(expected.x, 0.0001)),
::testing::Field(&Foo::y, ::testing::DoubleNear(expected.y, 0.0001))
);
}
auto EqBar(const Bar& expected)
{
return ::testing::AllOf(
::testing::Field(&Bar::foo, EqFoo(expected.foo)),
::testing::Field(&Bar::i, expected.i)
);
}
更通用的方法是使用重载:
auto MatchDouble(double expected)
{
return ::testing::DoubleNear(expected.x, 0.0001);
}
auto MatchFoo(::testing::Matcher<double> x, ::testing::Matcher<double> y)
{
return ::testing::AllOf(
::testing::Field(&Foo::x, x),
::testing::Field(&Foo::y, y)
);
}
auto MatchFoo(double x, double y)
{
return MatchFoo(MatchDouble(x), MatchDouble(y));
}
auto MatchBar(::testing::Matcher<Foo> foo, ::testing::Matcher<int> i)
{
return ::testing::AllOf(
::testing::Field(&Bar::foo, foo),
::testing::Field(&Bar::i, expected.i),
);
}
auto MatchBar(const Bar& expected)
{
return MatchBar(expected.foo, expected.i);
}
所以你的测试:
TEST_F(TestClass, BarTest)
{
Bar bar_val{{10.12, 76.43}, 78};
Bar bar_exp{{10.12, 99.99}, 78};
EXPECT_THAT(bar_val, MatchBar(bar_exp));
// or - e.g. you can match only Bar::y if other things are irrelevant in your test
EXPECT_THAT(bar_val, MatchBar(MatchFoo(_, MatchDouble(2.001)), _);
}
无论如何 - 使用 MATCHER_P
应该是相当罕见的情况,我自己的观察是这个宏确实被过度使用了。
如果您的项目是 pre-C++14 - 使用 ::testing::Matcher<T>
而不是 auto
作为所有这些函数的 return 类型。