web-dev-qa-db-fra.com

Comparaison des tableaux dans le test google?

Je cherche à comparer deux tableaux dans le test google. Dans UnitTest ++, cela se fait via CHECK_ARRAY_EQUAL. Comment faites-vous dans le test google?

69
Tobias Furuholm

Je suggérerais vraiment de regarder Google C++ Mocking Framework . Même si vous ne voulez rien vous moquer, cela vous permet d'écrire facilement des assertions assez compliquées.

Par exemple

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

Il y a beaucoup de matchers pour toutes les situations possibles, et vous pouvez les combiner pour réaliser presque n'importe quoi.

Je vous ai dit que ElementsAre n'a besoin que de la méthode iterators et size() sur une classe pour fonctionner? Il fonctionne donc non seulement avec n'importe quel conteneur de STL, mais également avec des conteneurs personnalisés.

Google Mock prétend être presque aussi portable que Google Test et franchement, je ne vois pas pourquoi vous ne l'utiliseriez pas. C'est purement génial.

98
vava

Si vous avez juste besoin de vérifier si les tableaux sont égaux, la force brute fonctionne également:

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

// initialize arr1 and arr2

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

Cependant, cela ne vous dit pas quel élément diffère.

16
BЈовић

Si vous souhaitez comparer un pointeur de tableau de style c à un tableau à l'aide de Google Mock, vous pouvez passer par std :: vector. Par exemple:

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

ElementsAreArray de Google Mock accepte également le pointeur et la longueur qui permettent la comparaison de deux pointeurs de tableau de style C. Par exemple:

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

J'ai passé beaucoup trop de temps à essayer de reconstituer cela. Merci à ce post StackOverlow pour le rappel sur l'initialisation de l'itérateur std :: vector. Notez que cette méthode copiera les éléments du tableau tampon dans le vecteur std :: avant la comparaison.

13
Matt Liberty

J'avais exactement la même question, j'ai donc écrit quelques macros qui font des comparaisons entre deux conteneurs génériques. Il est extensible à N'IMPORTE QUEL conteneur qui a const_iterator, begin et end. S'il échoue, il affichera un message détaillé indiquant où le tableau s'est mal passé et le fera pour chaque élément qui échoue; il s'assurera qu'ils sont de la même longueur; et l'emplacement dans votre code qu'il signale comme défaillant est la même ligne où vous appelez 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 )

J'espère que cela fonctionne pour vous (et que vous vérifiez réellement cette réponse deux mois après la soumission de votre question).

9
Seth Johnson

J'ai rencontré un problème similaire avec la comparaison de tableaux dans test google.

Étant donné que j'avais besoin d'une comparaison avec le base void* et char* (pour les tests de code de bas niveau), je ne pense pas non plus google mock (que j'utilise également dans le projet) ou la grande macro de Seth pourrait m'aider dans la situation particulière. J'ai écrit la macro suivante:

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

Les transtypages sont là pour rendre la macro utilisable lors de la comparaison de void* à d'autres choses:

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

Tobias dans les commentaires a suggéré de couler void* à char* et en utilisant EXPECT_STREQ, une macro que j'ai en quelque sorte manquée auparavant - qui ressemble à une meilleure alternative.

4
nietaki

Voici une assertion que j'ai écrite pour comparer [des fragments de] deux tableaux à virgule flottante:

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

L'utilisation dans Google Testing Framework est la suivante:

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

En cas d'erreur, quelque chose comme la sortie suivante est produite:

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

Pour une discussion approfondie sur la comparaison des valeurs à virgule flottante en général, veuillez consulter this .

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

Source

J'ai utilisé une boucle classique à travers tous les éléments. Vous pouvez utiliser SCOPED_TRACE pour lire dans quelle itération les éléments du tableau diffèrent. Cela vous fournit des informations supplémentaires par rapport à certaines autres approches et est facile à lire.

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]);
}
2
Wintermute