gpt4 book ai didi

c++ - 如何为二维数组编写一个好的GMock匹配器?

转载 作者:行者123 更新时间:2023-12-02 10:18:18 25 4
gpt4 key购买 nike

对于我的C++代码,我需要在二维矩阵上进行一组有限的代数运算。我决定使用std::array来实现此目的,如下所示:

template <typename T, size_t N, size_t M>
using array_2d = std::array<std::array<T, M>, N>;

我该如何正确编写此类型的GMock匹配器,以比较两个这样的 double 矩阵?
我想出了一个不太聪明的方法:
MATCHER_P(Arrays2dDoubleEq, expected, "") {
for (int i = 0; i < arg.size(); i++) {
for (int j = 0; j < arg[i].size(); j++) {
EXPECT_THAT(arg[i][j], DoubleEq(expected[i][j]));
}
}
return true;
}

MATCHER_P2(Arrays2dDoubleNear, expected, max_abs_err, "") {
for (int i = 0; i < arg.size(); i++) {
for (int j = 0; j < arg[i].size(); j++) {
EXPECT_THAT(arg[i][j], DoubleNear(expected[i][j], max_abs_err));
}
}
return true;
}

我使用的像: EXPECT_THAT(result, Arrays2dDoubleEq(expected));
这不仅看起来很难编码,而且也无法提供很好的反馈。当矩阵不匹配时,失败断言的输出将是一堆不相等的double。失败的测试输出很难读取,并且缺少有关矩阵索引的信息。

我认为可以以更好的方式来完成(并且应该做到)。我已经看过一些文档和GMock食谱。尽管容器有一些匹配器,但我无法使用它们来一次比较两个嵌套数组。

谁能指出我应该使用哪些GMock功能来使此匹配器更好?或者,也许有人可以指出我应该仔细阅读的文档部分,以了解此处可能缺少的内容?

最佳答案

您可能考虑的一件事是显式地从匹配器返回falsetrue而不是调用断言。然后,您可以使用result_listener提供有关比赛中到底出了什么问题的其他信息。您还应该在执行检查之前检查数组尺寸,以避免未定义的行为

using testing::DoubleEq;
using testing::Value;
using testing::Not;

MATCHER_P(Arrays2dDoubleEq, expected, "") {
if (arg.size() != expected.size())
{
*result_listener << "arg.size() != expected.size() ";
*result_listener << arg.size() << " vs " << expected.size();
return false;
}
for (size_t i = 0; i < arg.size(); i++) {
if (arg[i].size() != expected[i].size())
{
*result_listener << "arg[i].size() != expected[i].size() i = " << i << "; ";
*result_listener << arg[i].size() << " vs " << expected[i].size();
return false;
}
for (size_t j = 0; j < arg[i].size(); j++) {
if (!Value(arg[i][j], DoubleEq(expected[i][j])))
{
*result_listener << "element(" << i << ", " << j << ") mismatch ";
*result_listener << arg[i][j] << " vs " << expected[i][j];
return false;
}
}
}
return true;
}

TEST(xxx, yyy)
{
array_2d<double, 2, 3> arr1 = {std::array<double, 3>({1, 2, 3}), std::array<double, 3>({4, 5, 6})};
array_2d<double, 2, 3> arr2 = arr1;
array_2d<double, 2, 3> arr3 = arr1;
arr3[0][0] = 69.69;
array_2d<double, 5, 6> arr4;
ASSERT_THAT(arr1, Arrays2dDoubleEq(arr2));
ASSERT_THAT(arr2, Not(Arrays2dDoubleEq(arr3)));
ASSERT_THAT(arr2, Not(Arrays2dDoubleEq(arr4)));
}

不幸的是,我还没有弄清楚如何告诉gmock不要在 std::arrayValue of反馈字段中打印 Expected的内容。在 docs中,他们提到了 void PrintTo函数,但对我而言不起作用。

===编辑===

如果可以创建一个2D数组类而不是typedef,则可以通过提供 operator<<重载来轻松抑制gmock困惑的输出:
template <typename T, size_t N, size_t M>
struct Array2D
{
std::array<std::array<T, M>, N> data;
};

template <typename T, size_t N, size_t M>
std::ostream& operator<<(std::ostream& os, const Array2D<T, N, M>&)
{
os << "Array2D<" << typeid(T).name() << "," << N << "," << M << ">";
return os;
}

然后,您需要稍微修改匹配器以使用 data类字段,而不是直接使用 operator[]size()。或者,您可以在类(class)中重载它们。

如果您想要@JanHackenberg的注释,则在匹配器中只需设置标记 result = false而不是 return(我不会这样做,因为对于大数组,它将不可读)。

关于c++ - 如何为二维数组编写一个好的GMock匹配器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61172317/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com