So sánh các mảng trong google test?


81

Tôi đang tìm cách so sánh hai mảng trong thử nghiệm của Google. Trong UnitTest ++, điều này được thực hiện thông qua CHECK_ARRAY_EQUAL. Làm thế nào để bạn làm điều đó trong thử nghiệm google?

Câu trả lời:


115

Tôi thực sự khuyên bạn nên xem Google C ++ Mocking Framework . Ngay cả khi bạn không muốn chế nhạo bất cứ điều gì, nó cho phép bạn viết các xác nhận khá phức tạp một cách dễ dàng.

Ví dụ

//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), _));

Có rất nhiều công cụ phù hợp cho mọi tình huống có thể xảy ra và bạn có thể kết hợp chúng để đạt được hầu hết mọi thứ.

Tôi đã nói với bạn rằng ElementsArechỉ cần iteratorssize()phương thức trên một lớp để hoạt động? Vì vậy, nó không chỉ hoạt động với bất kỳ vùng chứa nào từ STL mà còn với các vùng chứa tùy chỉnh.

Google Mock tuyên bố gần như di động như Google Test và thành thật mà nói, tôi không hiểu tại sao bạn không sử dụng nó. Nó chỉ hoàn toàn là tuyệt vời.


7
Tôi sử dụng google mock. Và tôi đồng ý rằng nó thật tuyệt vời. Tôi không bao giờ mong đợi để thấy một cái gì đó giống như nó cho C ++.
Tobias Furuholm

2
ElementsAreArraytốt hơn là so sánh các mảng, vì ElementsArecó giới hạn 10 phần tử.
BЈовић

2
Lưu ý rằng bạn có thể muốn sử dụng EXPECT_THAT thay vì ASSERT_THAT trong các thử nghiệm.
arhuaco

điều gì sẽ xảy ra nếu các phần tử là std :: string? tôi đã nhận một lỗi mối liên kết testing::Matcher<std::string const&>::Matcher(char const*)không được định nghĩa
Frank Liu

1
Như BЈовић đã đề cập ElementsAreArray ở đây là một ví dụ để sử dụng điều đó: EXPECT_THAT(v, ElementsAreArray(u));mà tôi đã sử dụng nhiều hơn các ví dụ hiện tại.
Zitrax

18

Nếu bạn chỉ cần kiểm tra xem các mảng có bằng nhau hay không, thì lực lượng vũ phu cũng hoạt động:

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

// initialize arr1 and arr2

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

Tuy nhiên, điều này không cho bạn biết yếu tố nào khác nhau.


15

Nếu bạn muốn so sánh con trỏ mảng kiểu c với một mảng bằng Google Mock, bạn có thể đi qua std :: vector. Ví dụ:

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's ElementsAreArray cũng chấp nhận con trỏ và độ dài cho phép so sánh hai con trỏ mảng kiểu c. Ví dụ:

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

Tôi đã mất quá nhiều thời gian để cố gắng ghép nối điều này lại với nhau. Cảm ơn bài đăng StackOverflow này cho lời nhắc về khởi tạo trình lặp vectơ std ::. Lưu ý rằng phương thức này sẽ sao chép các phần tử mảng đệm vào vector std :: trước khi so sánh.


1
Nếu lỗi trong mã đang được kiểm tra xảy ra buffer_size, giá trị được trả về từ mã đang được kiểm tra, được đặt không chính xác (size_t)-1, đây không phải là một lỗi phổ biến, thì phương thức tạo vectơ sẽ cố gắng tạo ra một vectơ rất lớn! Chương trình thử nghiệm có thể bị giết do giới hạn tài nguyên hoặc lỗi hết bộ nhớ, hoặc chỉ là sự cố đơn thuần, chứ không phải là xác nhận thử nghiệm không thành công. Với C ++ 20, việc sử dụng std::spanthay vì vectơ sẽ ngăn chặn điều này, vì nó không cần sao chép bộ đệm vào một vùng chứa mới.
TrentP

Điều gì đó tương tự có thể đạt được bằng cách diễn giải lại việc truyền dữ liệu thực tế sang con trỏ std :: array <type, size> và tham chiếu đến ptr. trong khẳng định. Một cái gì đó như: gist.github.com/daantimmer/…
Daan Timmer

13
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;
}

Nguồn


Tôi khá thích nó. Nó không yêu cầu sao chép dữ liệu vào vùng chứa stl và nó khá đơn giản. Việc bao bọc điều này trong một macro cho một kiểu so sánh mảng phổ biến (như vectơ hoặc ma trận), được thực hiện đơn giản và hoàn thành công việc.
johnb003 29/12/17

9

Tôi đã có cùng một câu hỏi, vì vậy tôi đã viết một vài macro để so sánh giữa hai vùng chứa chung. Đó là mở rộng để chứa bất kỳ mà có const_iterator, beginend. Nếu không thành công, nó sẽ hiển thị một thông báo chi tiết về vị trí mảng bị lỗi và sẽ thực hiện như vậy cho mọi phần tử bị lỗi; nó sẽ đảm bảo rằng chúng có cùng chiều dài; và vị trí trong mã của bạn mà nó báo cáo là không thành công là cùng một dòng nơi bạn gọi 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 )

Hy vọng điều này hiệu quả với bạn (và bạn thực sự kiểm tra câu trả lời này hai tháng sau khi câu hỏi của bạn được gửi).


Đó là một cách tiếp cận tuyệt vời! Có lẽ bạn có thể cung cấp cái này cho google để họ thêm nó vào khuôn khổ?
Tobias Furuholm

2
Họ cho biết ( code.google.com/p/googletest/issues/detail?id=231 ) rằng họ không khuyến khích thêm macro và chức năng này khả dụng ở một mức độ nào đó trong khung Google Mock.
Seth Johnson

5

Tôi đã gặp phải một vấn đề tương tự khi so sánh các mảng trong thử nghiệm của Google .

Vì tôi cần so sánh với cơ bản void*char*(để kiểm tra mã cấp thấp), tôi không nghĩ rằng google mock (mà tôi cũng đang sử dụng trong dự án) hoặc macro tuyệt vời của Seth có thể giúp tôi trong tình huống cụ thể. Tôi đã viết macro sau:

#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]);\
    }\
    }

Các phôi ở đó để làm cho macro có thể sử dụng được khi so sánh void*với những thứ khác:

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

Tobias trong các nhận xét đã đề xuất truyền void*đến char*và sử dụng EXPECT_STREQ, một macro mà tôi đã bỏ qua bằng cách nào đó trước đây - có vẻ như một sự thay thế tốt hơn.


2
Tôi muốn truyền khoảng trống * thành ký tự * và sử dụng EXPECT_STREQ. Điều đó sẽ không hoạt động tốt?
Tobias Furuholm

Một trong những lý do tôi đăng câu trả lời của mình là vì tôi hy vọng ai đó sẽ đề xuất một giải pháp thay thế tốt hơn. Có vẻ như bạn đã làm, Tobias :)
nietaki

EXPECT_STREQkhông hoạt động đối với các mảng tùy ý chứa không phần tử. Tôi vẫn bỏ phiếu cho giải pháp của @nietaki.
Mohammad Dashti

4

Dưới đây là khẳng định tôi đã viết để so sánh [các đoạn của] hai mảng dấu phẩy động:

/* 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();
}

Cách sử dụng trong Khung thử nghiệm của Google là:

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

Trong trường hợp xảy ra lỗi, kết quả giống như sau sẽ được tạo ra:

..\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

Để thảo luận kỹ lưỡng về việc so sánh các giá trị dấu phẩy động nói chung, vui lòng xem phần này .


3

Tôi đã sử dụng một vòng lặp cổ điển qua tất cả các phần tử. Bạn có thể sử dụng SCOPED_TRACE để đọc ra các phần tử của mảng khác nhau trong lần lặp nào. Điều này cung cấp cho bạn thông tin bổ sung so với một số cách tiếp cận khác và rất dễ đọc.

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]);
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.