गूगल टेस्ट में सरणियों की तुलना?


84

मैं Google परीक्षण में दो सरणियों की तुलना करना चाहता हूं। UnitTest ++ में यह CHECK_ARRAY_EQUAL के माध्यम से किया जाता है। आप इसे Google परीक्षण में कैसे करते हैं?

जवाबों:


120

मैं वास्तव में Google C ++ मॉकिंग फ्रेमवर्क को देखने का सुझाव दूंगा । यहां तक ​​कि अगर आप कुछ भी मजाक नहीं करना चाहते हैं, तो यह आपको आसानी से जटिल बयान लिखने की अनुमति देता है।

उदाहरण के लिए

//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()पद्धति की आवश्यकता है ? तो यह न केवल एसटीएल से किसी भी कंटेनर के साथ काम करता है बल्कि कस्टम कंटेनर के साथ भी काम करता है।

Google मॉक लगभग Google टेस्ट के रूप में पोर्टेबल होने का दावा करता है और स्पष्ट रूप से मैं यह नहीं देखता कि आप इसका उपयोग क्यों नहीं करेंगे। यह सिर्फ विशुद्ध रूप से भयानक है।


7
मैं google mock का उपयोग करता हूँ। और मैं मानता हूं कि यह कमाल है। मुझे C ++ के लिए ऐसा कुछ देखने की उम्मीद नहीं थी।
टोबियास फुरहोम

2
ElementsAreArrayसरणियों की तुलना करना बेहतर है, क्योंकि ElementsAreइसमें 10 तत्वों की सीमा है।
बिग

2
ध्यान दें कि आप परीक्षण में ASSERT_THAT के बजाय EXPECT_THAT का उपयोग करना चाह सकते हैं।
अर्हुको

1
जैसा कि BrayовиЈ ने ElementsAreArray का उल्लेख किया है, यह उस के उपयोग के लिए एक उदाहरण है: EXPECT_THAT(v, ElementsAreArray(u));जिसे मैंने वर्तमान उदाहरणों की तुलना में अधिक उपयोग किया है।
ज़िट्रैक्स

1
क्या वे gmock प्रोजेक्ट का हिस्सा हैं? या सिर्फ Gtest प्रोजेक्ट?
त्सुकिरोग्लू फोटी

18

यदि आपको केवल यह जांचने की आवश्यकता है कि क्या सरणियाँ समान हैं, तो ब्रूट बल भी काम करता है:

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

// initialize arr1 and arr2

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

हालाँकि, यह आपको नहीं बताता कि कौन सा तत्व अलग है।


15

यदि आप Google मॉक का उपयोग करके c-style array पॉइंटर की तुलना किसी ऐरे से करना चाहते हैं, तो आप std :: वेक्टर के माध्यम से जा सकते हैं। उदाहरण के लिए:

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 मॉक के ElementsAreArray भी पॉइंटर और लंबाई को स्वीकार करता है जो दो सी-स्टाइल ऐरे पॉइंटर्स की तुलना करने की अनुमति देता है। उदाहरण के लिए:

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

मैंने इस पर एक साथ काम करने के लिए बहुत लंबा समय बिताया। इस StackOverflow पोस्ट के लिए धन्यवाद std :: वेक्टर पुनरावृत्ति आरंभीकरण पर अनुस्मारक के लिए। ध्यान दें कि यह विधि बफर सरणी तत्वों की तुलना में पहले std :: वेक्टर में कॉपी करेगी।


1
यदि परीक्षण किए जा रहे कोड में बग ऐसा होता है buffer_size, जो परीक्षण के तहत कोड से लौटाया गया मान गलत तरीके से सेट हो जाता है (size_t)-1, जो कि कोई असामान्य त्रुटि नहीं है, तो वेक्टर निर्माता बहुत बड़े वेक्टर बनाने की कोशिश करेगा! परीक्षण कार्यक्रम विफल होने के बजाय संसाधन सीमा या मेमोरी त्रुटि से बाहर, या सिर्फ सादे दुर्घटना से मारा जा सकता है। C ++ 20 के साथ, std::spanवेक्टर के बजाय का उपयोग करके इसे रोकना चाहिए, क्योंकि इसे बफर को नए कंटेनर में कॉपी करने की आवश्यकता नहीं है।
TrentP

कुछ इसी तरह की वास्तविक स्थिति कास्टिंग को std :: array <type, size> pointer और dereferencing से ptr में डालकर प्राप्त किया जा सकता है। मुखर में। कुछ इस तरह: 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;
}

स्रोत


मुझे यह पसंद है। यह एक stl कंटेनर में डेटा कॉपी करने की आवश्यकता नहीं है, और यह सिर्फ काफी सरल है। एक सामान्य प्रकार की सरणी तुलना (जैसे कि वेक्टर या मैट्रिक्स) के लिए मैक्रो में लपेटकर बस काम किया जाता है और काम पूरा हो जाता है।
जॉन्ब 003

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 को प्रदान कर सकें, इसलिए वे इसे फ्रेमवर्क में जोड़ सकते हैं?
टोबियास फुरहोम

2
उन्होंने ( code.google.com/p/googletest/issues/detail?id=231 ) कहा कि वे मैक्रोज़ को जोड़ने को हतोत्साहित करते हैं, और Google मॉक ढांचे में यह कार्यक्षमता कुछ हद तक उपलब्ध है।
सेठ जॉनसन

5

मैं Google परीक्षण में सरणियों की तुलना करने के साथ एक समान समस्या में भाग गया ।

चूँकि मुझे बुनियादी void*और char*(निम्न-स्तरीय कोड परीक्षण के लिए) तुलना की आवश्यकता थी , इसलिए मैं या तो Google मॉक (जो कि मैं इस परियोजना में उपयोग कर रहा हूं) या सेठ के महान मैक्रो से किसी विशेष स्थिति में मेरी मदद नहीं कर सकते। मैंने निम्नलिखित मैक्रो लिखा है:

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

टिप्पणियों में टोबियास ने कास्टिंग void*करने char*और उपयोग करने का सुझाव दिया EXPECT_STREQ, एक मैक्रो जिसे मैं किसी भी तरह से पहले याद किया था - जो एक बेहतर विकल्प की तरह दिखता है।


2
मैं शून्य को * एक char * में डालना और EXPECT_STREQ का उपयोग करना पसंद करूंगा। क्या वह काम भी नहीं करेगा?
टोबियास फुरहोम

जिन कारणों से मैंने अपना उत्तर पोस्ट किया था उनमें से एक यह था कि मुझे उम्मीद थी कि कोई व्यक्ति बेहतर विकल्प सुझाएगा। ऐसा लगता है कि आपने किया, तोबियास :)
नीताकी

EXPECT_STREQशून्य तत्वों वाले मनमाने सरणियों के लिए काम नहीं करता है। मैं अभी भी @nietaki के समाधान के लिए मतदान करूंगा।
मोहम्मद दशती

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]);
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.