Ich möchte zwei Arrays in Google Test vergleichen. In UnitTest ++ erfolgt dies über CHECK_ARRAY_EQUAL. Wie machst du das in Google Test?
Ich möchte zwei Arrays in Google Test vergleichen. In UnitTest ++ erfolgt dies über CHECK_ARRAY_EQUAL. Wie machst du das in Google Test?
Antworten:
Ich würde wirklich empfehlen, sich Google C ++ Mocking Framework anzuschauen . Selbst wenn Sie sich über nichts lustig machen möchten, können Sie mit Leichtigkeit ziemlich komplizierte Aussagen schreiben.
Zum Beispiel
//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), _));
Es gibt viele Matcher für jede mögliche Situation, und Sie können sie kombinieren, um fast alles zu erreichen.
Habe ich dir gesagt, dass ElementsAre
nur eine Methode iterators
und eine size()
Methode für eine Klasse funktionieren? Es funktioniert also nicht nur mit jedem Container von STL, sondern auch mit benutzerdefinierten Containern.
Google Mock behauptet, fast so portabel zu sein wie Google Test, und ehrlich gesagt verstehe ich nicht, warum Sie es nicht verwenden würden. Es ist einfach nur großartig.
ElementsAreArray
ist besser, Arrays zu vergleichen, da ElementsAre
es eine Grenze von 10 Elementen hat.
testing::Matcher<std::string const&>::Matcher(char const*)
nicht definiert
EXPECT_THAT(v, ElementsAreArray(u));
das ich mehr verwendet habe als die aktuellen Beispiele.
Wenn Sie einen Array-Zeiger im C-Stil mit Google Mock mit einem Array vergleichen möchten, können Sie std :: vector durchgehen. Zum Beispiel:
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 von Google Mock akzeptiert auch Zeiger und Längen, mit denen zwei Array-Zeiger im C-Stil verglichen werden können. Zum Beispiel:
ASSERT_THAT(std::vector<uint8_t>(buffer, buffer + buffer_size),
::testing::ElementsAreArray(buffer, buffer_size));
Ich habe viel zu lange versucht, dies zusammenzusetzen. Vielen Dank an diesen StackOverflow-Beitrag für die Erinnerung an die Initialisierung des std :: vector-Iterators. Beachten Sie, dass diese Methode die Pufferarray-Elemente vor dem Vergleich in den Vektor std :: kopiert.
buffer_size
Wert falsch gesetzt wird (size_t)-1
, was kein ungewöhnlicher Fehler ist, versucht der Vektorkonstruktor, einen sehr großen Vektor zu erstellen ! Das Testprogramm wird möglicherweise mit einem Ressourcenlimit oder einem Speicherfehler oder einem einfachen Absturz beendet, anstatt dass die Testzusicherung fehlschlägt. In C ++ 20 sollte die Verwendung std::span
anstelle von Vektor dies verhindern, da der Puffer nicht in einen neuen Container kopiert werden muss.
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;
}
Ich hatte genau die gleiche Frage, also habe ich ein paar Makros geschrieben, die Vergleiche zwischen zwei generischen Containern anstellen. Es ist erweiterbar auf jeden Behälter, der hat const_iterator
, begin
und end
. Wenn dies fehlschlägt, wird eine ausführliche Meldung angezeigt, wo das Array fehlerhaft war, und dies für jedes Element, das fehlschlägt. es wird sicherstellen, dass sie die gleiche Länge haben; und der Ort in Ihrem Code, den er als fehlerhaft meldet, ist dieselbe Zeile, in der Sie anrufen 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 )
Hoffe, dass dies für Sie funktioniert (und dass Sie diese Antwort zwei Monate nach dem Absenden Ihrer Frage tatsächlich überprüfen).
Ich hatte ein ähnliches Problem beim Vergleichen von Arrays in Google Test .
Da ich einen Vergleich mit Basic void*
und char*
(für Low-Level-Code-Tests) brauchte , habe ich weder Google Mock (das ich auch im Projekt verwende) noch Seths großartiges Makro, das mir in der jeweiligen Situation helfen könnte. Ich habe folgendes Makro geschrieben:
#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]);\
}\
}
Die Casts dienen dazu, das Makro im Vergleich void*
zu anderen Dingen nutzbar zu machen :
void* retrieved = ptr->getData();
EXPECT_EQ(6, ptr->getSize());
EXPECT_ARRAY_EQ(char, "data53", retrieved, 6)
Tobias schlug in den Kommentaren vor , ein Makro void*
zu char*
verwenden EXPECT_STREQ
, ein Makro, das ich vorher irgendwie vermisst hatte - was nach einer besseren Alternative aussieht.
EXPECT_STREQ
funktioniert nicht für beliebige Arrays, die keine Elemente enthalten. Ich würde immer noch für @nietakis Lösung stimmen.
Unten ist eine Behauptung, die ich geschrieben habe, um [Fragmente von] zwei Gleitkomma-Arrays zu vergleichen:
/* 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();
}
Die Verwendung innerhalb des Google Testing Framework ist folgende:
EXPECT_TRUE(AreFloatingPointArraysEqual(expectedArray, actualArray, lengthToCompare));
Im Fehlerfall wird etwa die folgende Ausgabe erzeugt:
..\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
Weitere Informationen zum Vergleich von Gleitkommawerten im Allgemeinen finden Sie hier .
Ich habe eine klassische Schleife durch alle Elemente verwendet. Mit SCOPED_TRACE können Sie auslesen, in welcher Iteration sich die Array-Elemente unterscheiden. Dies bietet Ihnen im Vergleich zu einigen anderen Ansätzen zusätzliche Informationen und ist leicht zu lesen.
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]);
}