Одна вещь, которую вы могли бы рассмотреть, - это явное возвращение false
или true
из вашего сопоставителя вместо вызова утверждений. Затем вы можете использовать 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::array
в Value of
и Expected
поля обратной связи. в документах они упоминают функцию void PrintTo
, но она не работает для меня.
=== РЕДАКТИРОВАТЬ ===
Если вы можете создайте класс 2D-массива вместо typedef, тогда легко подавить беспорядочный вывод gmock, предоставив перегрузку operator<<
:
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;
}
Затем вам нужно немного изменить matcher, чтобы использовать поле класса data
вместо operator[]
и size()
напрямую. Или вы можете перегрузить их для вашего класса.
Если вам нужен комментарий @JanHackenberg, то внутри вашего сопоставителя просто установите флаг result = false
вместо return
(хотя я бы этого не сделал, потому что для больших массивов он не будет читаться).