google测试中数组的比较?

问题描述 投票:0回答:11

我想在谷歌测试中比较两个数组。在 UnitTest++ 中,这是通过 CHECK_ARRAY_EQUAL 完成的。你在谷歌测试中是如何做到的?

c++ unit-testing googletest
11个回答
168
投票

我真的建议查看Google C++ Mocking Framework。即使您不想模拟任何东西,它也可以让您轻松编写相当复杂的断言。

例如

//checks that vector v is {5, 10, 15}
ASSERT_THAT(v, ElementsAre(5, 10, 15));

//checks that map m only have elements 1 => 10, 2 => 20
ASSERT_THAT(m, ElementsAre(Pair(1, 10), Pair(2, 20)));

//checks that in vector v all the elements are greater than 10 and less than 20
ASSERT_THAT(v, Each(AllOf(Gt(10), Lt(20))));

//checks that vector v consist of 
//   5, number greater than 10, anything.
ASSERT_THAT(v, ElementsAre(5, Gt(10), _));

针对每种可能的情况都有大量的匹配器,您可以将它们组合起来以实现几乎任何目标。

我有没有告诉过你,

ElementsAre
只需要类上的
iterators
size()
方法就可以工作?因此它不仅适用于 STL 中的任何容器,也适用于自定义容器。

Google Mock 声称几乎与 Google Test 一样便携,坦率地说,我不明白你为什么不使用它。这简直太棒了。


27
投票

如果你只需要检查数组是否相等,那么暴力破解也可以:

int arr1[10];
int arr2[10];

// initialize arr1 and arr2

EXPECT_TRUE( 0 == std::memcmp( arr1, arr2, sizeof( arr1 ) ) );

但是,这并不能告诉您哪个元素不同。


25
投票
ASSERT_EQ(x.size(), y.size()) << "Vectors x and y are of unequal length";

for (int i = 0; i < x.size(); ++i) {
  EXPECT_EQ(x[i], y[i]) << "Vectors x and y differ at index " << i;
}

来源


22
投票

如果你想使用 Google Mock 比较 C 风格的数组指针和数组,你可以通过 std::vector。 例如:

uint8_t expect[] = {1, 2, 3, 42};
uint8_t * buffer = expect;
uint32_t buffer_size = sizeof(expect) / sizeof(expect[0]);
ASSERT_THAT(std::vector<uint8_t>(buffer, buffer + buffer_size), 
            ::testing::ElementsAreArray(expect));

Google Mock 的 ElementsAreArray 还接受指针和长度,允许比较两个 C 样式数组指针。 例如:

ASSERT_THAT(std::vector<uint8_t>(buffer, buffer + buffer_size), 
            ::testing::ElementsAreArray(buffer, buffer_size));

我花了太长时间试图将其拼凑起来。 感谢 this StackOverflow post 关于 std::vector 迭代器初始化的提醒。 请注意,此方法会在比较之前将缓冲区数组元素复制到 std::vector 中。


11
投票

我有完全相同的问题,所以我编写了几个宏来对两个通用容器进行比较。它可扩展到任何具有

const_iterator
begin
end
的容器。如果失败,它将显示一条详细消息,说明数组出错的位置,并对每个失败的元素执行此操作;它将确保它们的长度相同;并且代码中报告失败的位置与您调用
EXPECT_ITERABLE_EQ( std::vector< double >, a, b)
的位置位于同一行。

//! Using the google test framework, check all elements of two containers
#define EXPECT_ITERABLE_BASE( PREDICATE, REFTYPE, TARTYPE, ref, target) \
    { \
    const REFTYPE& ref_(ref); \
    const TARTYPE& target_(target); \
    REFTYPE::const_iterator refIter = ref_.begin(); \
    TARTYPE::const_iterator tarIter = target_.begin(); \
    unsigned int i = 0; \
    while(refIter != ref_.end()) { \
        if ( tarIter == target_.end() ) { \
            ADD_FAILURE() << #target " has a smaller length than " #ref ; \
            break; \
        } \
        PREDICATE(* refIter, * tarIter) \
            << "Containers " #ref  " (refIter) and " #target " (tarIter)" \
               " differ at index " << i; \
        ++refIter; ++tarIter; ++i; \
    } \
    EXPECT_TRUE( tarIter == target_.end() ) \
        << #ref " has a smaller length than " #target ; \
    }

//! Check that all elements of two same-type containers are equal
#define EXPECT_ITERABLE_EQ( TYPE, ref, target) \
    EXPECT_ITERABLE_BASE( EXPECT_EQ, TYPE, TYPE, ref, target )

//! Check that all elements of two different-type containers are equal
#define EXPECT_ITERABLE_EQ2( REFTYPE, TARTYPE, ref, target) \
    EXPECT_ITERABLE_BASE( EXPECT_EQ, REFTYPE, TARTYPE, ref, target )

//! Check that all elements of two same-type containers of doubles are equal
#define EXPECT_ITERABLE_DOUBLE_EQ( TYPE, ref, target) \
    EXPECT_ITERABLE_BASE( EXPECT_DOUBLE_EQ, TYPE, TYPE, ref, target )

希望这对您有用(并且您在提交问题两个月后实际上检查了此答案)。


7
投票

我使用了经典的循环遍历所有元素。您可以使用 SCOPED_TRACE 来读出数组元素在哪一次迭代中有所不同。与其他一些方法相比,这为您提供了更多信息,并且易于阅读。

for (int idx=0; idx<ui16DataSize; idx++)
{
    SCOPED_TRACE(idx); //write to the console in which iteration the error occurred
    ASSERT_EQ(array1[idx],array2[idx]);
}

5
投票

我在 google test 中比较数组时遇到了类似的问题。

由于我需要与基本的

void*
char*
(用于低级代码测试)进行比较,我认为Google Mock(我也在项目中使用)或Seth的伟大宏可以提供帮助我在特定情况下。我写了以下宏:

#define EXPECT_ARRAY_EQ(TARTYPE, reference, actual, element_count) \
    {\
    TARTYPE* reference_ = static_cast<TARTYPE *> (reference); \
    TARTYPE* actual_ = static_cast<TARTYPE *> (actual); \
    for(int cmp_i = 0; cmp_i < element_count; cmp_i++ ){\
      EXPECT_EQ(reference_[cmp_i], actual_[cmp_i]);\
    }\
    }

强制转换是为了使宏在将

void*
与其他东西进行比较时可用:

  void* retrieved = ptr->getData();
  EXPECT_EQ(6, ptr->getSize());
  EXPECT_ARRAY_EQ(char, "data53", retrieved, 6)

Tobias 在评论中建议将

void*
转换为
char*
并使用
EXPECT_STREQ
,这是我之前错过的一个宏 - 这看起来是一个更好的选择。


4
投票

下面是我写的一个断言,用于比较两个浮点数组的[片段]:

/* See
http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
for thorough information about comparing floating point values.
For this particular application we know that the value range is -1 to 1 (audio signal),
so we can compare to absolute delta of 1/2^22 which is the smallest representable value in
a 22-bit recording.
*/
const float FLOAT_INEQUALITY_TOLERANCE = float(1.0 / (1 << 22));


template <class T>
::testing::AssertionResult AreFloatingPointArraysEqual(
                                const T* const expected,
                                const T* const actual,
                                unsigned long length)
{
    ::testing::AssertionResult result = ::testing::AssertionFailure();
    int errorsFound = 0;
    const char* separator = " ";
    for (unsigned long index = 0; index < length; index++)
    {
        if (fabs(expected[index] - actual[index]) > FLOAT_INEQUALITY_TOLERANCE)
        {
            if (errorsFound == 0)
            {
                result << "Differences found:";
            }
            if (errorsFound < 3)
            {
                result << separator
                        << expected[index] << " != " << actual[index]
                        << " @ " << index;
                separator = ", ";
            }
            errorsFound++;
        }
    }
    if (errorsFound > 0)
    {
        result << separator << errorsFound << " differences in total";
        return result;
    }
    return ::testing::AssertionSuccess();
}

Google 测试框架内的用法是这样的:

EXPECT_TRUE(AreFloatingPointArraysEqual(expectedArray, actualArray, lengthToCompare));

如果出现错误,会生成类似以下输出:

..\MyLibraryTestMain.cpp:145: Failure
Value of: AreFloatingPointArraysEqual(expectedArray, actualArray, lengthToCompare)
  Actual: false (Differences found: 0.86119759082794189 != 0.86119747161865234 @ 14, -0.5552707314491272 != -0.55527061223983765 @ 24, 0.047732405364513397 != 0.04773232713341713 @ 36, 339 differences in total)
Expected: true

有关比较一般浮点值的深入讨论,请参阅 这个


2
投票

在今天的版本中,您只需为枚举类类型声明

operator<<
,但是 与枚举位于相同的命名空间中(请参阅 https://github.com/google/googletest/blob/main/docs/ Advanced.md#teaching-googletest-how-to-print-your-values)

namespace Foo
{
    enum class Bar
    {
        Hello,
        Goodbye,
    };

    // In the same namespace !!
    inline std::ostream& operator<<(std::ostream& os, const Bar& v)
    {
        switch (v)
        {
            case Bar::Hello: os << "Hello"; break;
            case Bar::Goodbye: os << "Goodbye"; break;
        }
        return os;
    }
}

TEST(Suite, Demo1)
{
    using namespace Foo;

    vector<Bar> vec1 = { Bar::Hello, Bar::Goodbye };
    vector<Bar> vec2 = { Bar::Goodbye };

    ASSERT_EQ(vec1, vec2);
}
test.cpp(106): error: Expected equality of these values:
  vec1
    Which is: { Hello, Goodbye }
  vec2
    Which is: { Goodbye }
[  FAILED  ] Suite.Demo1 (1 ms)

`` 

0
投票

我所做的是制作向量的列表初始化就绪打印并比较两个字符串。

类似这样的:

std::stringstream expected;
expected_triangles << expected_vector;

std::stringstream output;
o_triangles << output_vector;

EXPECT_EQ(o_triangles.str(), expected_triangles.str());

为此,您需要定义:

///
/// \brief operator << print a vector in a list-initialization friendly format
/// \param out
/// \param point
/// \return
///
template <typename T>
std::ostream &operator<<(std::ostream &out, std::vector<T> const &vector) 

{
    out << "{";

    if (!vector.empty())
    {
        out << vector[0];
    }

    for (size_t i = 1; i < vector.size(); i++)
    {
        out << ", " << vector[i];
    }

    out << "}";

    return out;
}

从实时数据创建测试用例也非常方便,因为您只需要记录数据,然后使用它来初始化测试数组。


0
投票

现在您可以在

std::vector
std::array
上使用标准断言宏。他们使用内置的比较运算符:

std::vector<int> vec1 {1,2,3,4};
std::vector<int> vec2 {1,2,3,5};
EXPECT_EQ(vec1, vec2);

std::vector<int> vec3 {1,2,3,4};
std::vector<int> vec4 {1,2,3,4,5};
EXPECT_EQ(vec3, vec4);

std::array<int, 4> arr1 {1,2,3,4};
std::array<int, 4> arr2 {1,2,4,4};
EXPECT_EQ(arr1, arr2);

打印

Test.cpp: Failure
Expected equality of these values:
  vec1
    Which is: { 1, 2, 3, 4 }
  vec2
    Which is: { 1, 2, 3, 5 }
Test.cpp: Failure
Expected equality of these values:
  vec3
    Which is: { 1, 2, 3, 4 }
  vec4
    Which is: { 1, 2, 3, 4, 5 }
Test.cpp: Failure
Expected equality of these values:
  arr1
    Which is: { 1, 2, 3, 4 }
  arr2
    Which is: { 1, 2, 4, 4 }
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.