Google 테스트의 배열 비교?


답변:


119

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필요한 방법 iteratorssize()방법 만 말씀 드렸나요 ? 따라서 STL의 모든 컨테이너뿐만 아니라 사용자 지정 컨테이너에서도 작동합니다.

Google Mock은 Google Test만큼 이식성이 있다고 주장하며 솔직히 왜 그것을 사용하지 않는지 모르겠습니다. 순전히 굉장합니다.


7
Google mock을 사용합니다. 그리고 나는 그것이 굉장하다는 것에 동의합니다. 나는 C ++에서 이와 같은 것을 기대하지 못했습니다.
Tobias Furuholm

2
ElementsAreArrayElementsAre요소가 10 개로 제한 되므로 배열을 비교하는 것이 좋습니다 .
BЈовић '152015-09-01

2
테스트에서 ASSERT_THAT 대신 EXPECT_THAT을 사용할 수 있습니다.
arhuaco

1
BЈовић가 ElementsAreArray를 언급했듯이 여기에 EXPECT_THAT(v, ElementsAreArray(u));그 사용의 예가 있습니다. 저는 현재의 예보다 더 많이 사용했습니다.
Zitrax

1
gmock 프로젝트의 일부입니까 아니면 Gtest 프로젝트입니까?
Tsakiroglou Fotis

18

배열이 동일한 지 확인해야하는 경우 무차별 대입도 작동합니다.

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

// initialize arr1 and arr2

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

그러나 이것은 어떤 요소가 다른지 알려주지 않습니다.


15

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));

나는 이것을 합치려고 너무 오래 보냈다. std :: vector 반복기 초기화에 대한 알림에 대한 이 StackOverflow 게시물 에 감사드립니다 . 이 메서드는 비교 전에 버퍼 배열 요소를 std :: vector에 복사합니다.


1
테스트중인 코드의 버그가 테스트중인 buffer_size코드에서 반환 된 값이으로 잘못 설정되는 (size_t)-1경우 (일반적인 오류가 아닌 경우) 벡터 생성자는 매우 큰 벡터를 만들려고합니다! 테스트 프로그램은 테스트 어설 션이 실패하는 대신 리소스 제한 또는 메모리 부족 오류 또는 일반 크래시로 종료 될 수 있습니다. C ++ 20에서는 std::span벡터 대신 사용 하면 버퍼를 새 컨테이너에 복사 할 필요가 없기 때문에이를 방지 할 수 있습니다.
TrentP

actualData를 std :: array <type, size> 포인터로 다시 해석하고 ptr을 역 참조하면 비슷한 결과를 얻을 수 있습니다. 주장에서. 같은 뭔가 : gist.github.com/daantimmer/...
Daan 티 메르

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

출처


나는 이것 좀 좋아합니다. 데이터를 stl 컨테이너에 복사 할 필요가 없으며 매우 간단합니다. 일반적인 유형의 배열 비교 (예 : 벡터 또는 행렬)를 위해 매크로로 래핑하면 간단하게 완료되고 작업이 완료됩니다.
johnb003 dec.

9

나는 똑같은 질문을 했으므로 두 개의 일반 컨테이너를 비교하는 몇 가지 매크로를 작성했습니다. 그것은이 모든 컨테이너에 확장이다 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 )

이것이 당신에게 효과가 있기를 바랍니다 (그리고 질문이 제출 된 지 두 달 후에 실제로이 답변을 확인하십시오).


그것은 훌륭한 접근 방식입니다! Google에 제공하여 프레임 워크에 추가 할 수 있습니까?
Tobias Furuholm

2
그들은 ( code.google.com/p/googletest/issues/detail?id=231 ) 매크로 추가를 권장하지 않으며이 기능은 Google Mock 프레임 워크에서 어느 정도 사용할 수 있다고 말했습니다 .
Seth Johnson

5

Google 테스트 에서 배열을 비교하는 것과 비슷한 문제가 발생했습니다 .

기본 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


2
void *를 char *로 캐스팅하고 EXPECT_STREQ를 사용하는 것을 선호합니다. 잘 작동하지 않습니까?
토비아스 Furuholm

내 답변을 게시 한 이유 중 하나는 누군가가 더 나은 대안을 제안하기를 바 랐기 때문입니다. :), 당신이 한 토비아스 보인다
nietaki

EXPECT_STREQ0 요소를 포함하는 임의의 배열에는 작동하지 않습니다. 나는 여전히 @nietaki의 해결책에 투표 할 것입니다.
Mohammad Dashti

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

일반적으로 부동 소수점 값을 비교하는 방법에 대한 자세한 내용은 여기를 참조 하십시오 .


3

모든 요소에 고전적인 루프를 사용했습니다. 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]);
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.