Domanda

Sto usando test Boost di unit test del codice C ++.

Ho un vettore di valori che ho bisogno di confrontare con i risultati attesi, ma io non voglio controllare manualmente i valori in un ciclo:

BOOST_REQUIRE_EQUAL(values.size(), expected.size());

for( int i = 0; i < size; ++i )
{
    BOOST_CHECK_EQUAL(values[i], expected[i]);
}

Il problema principale è che il controllo ciclo non stampa l'indice, quindi richiede qualche ricerca per trovare la mancata corrispondenza.

ho potuto usare std::equal o std::mismatch sui due vettori, ma che richiederà un sacco di testo standard pure.

C'è un modo più pulito per fare questo?

È stato utile?

Soluzione

BOOST_CHECK_EQUAL_COLLECTIONS . Si tratta di una macro in test_tools.hpp che prende due coppie di iteratori:

BOOST_CHECK_EQUAL_COLLECTIONS(values.begin(), values.end(), 
                              expected.begin(), expected.end());

Si segnalerà gli indici ei valori che non corrispondente. Se le dimensioni non corrispondono, segnalerà che pure (e non sarà solo scappare la fine del vettore).


Si noti che se si desidera utilizzare o BOOST_CHECK_EQUAL BOOST_CHECK_EQUAL_COLLECTIONS con i tipi non-POD, è necessario implementare

bool YourType::operator!=(const YourType &rhs)  //  or OtherType
std::ostream &operator<<(std::ostream &os, const YourType &yt)

per il confronto e la registrazione, rispettivamente.
L'ordine dei iteratori passato al determina BOOST_CHECK_EQUAL_COLLECTIONS che è RHS e LHS del confronto != -. Il primo intervallo iteratore saranno i LHS nei confronti

Altri suggerimenti

Un po 'off-topic, tuttavia, quando a volte si ha la necessità di confrontare le collezioni di numeri in virgola mobile usando comparison con tolleranza allora questo frammento può essere utile:

// Have to make it a macro so that it reports exact line numbers when checks fail.
#define CHECK_CLOSE_COLLECTION(aa, bb, tolerance) { \
    using std::distance; \
    using std::begin; \
    using std::end; \
    auto a = begin(aa), ae = end(aa); \
    auto b = begin(bb); \
    BOOST_REQUIRE_EQUAL(distance(a, ae), distance(b, end(bb))); \
    for(; a != ae; ++a, ++b) { \
        BOOST_CHECK_CLOSE(*a, *b, tolerance); \
    } \
}

Questa non stampa gli indici array di elementi mismatching, ma lo fa stampare i valori di disadattamenti con alta precisione, in modo che essi sono spesso facili da trovare.

Esempio di utilizzo:

auto mctr = pad.mctr();
std::cout << "mctr: " << io::as_array(mctr) << '\n';
auto expected_mctr{122.78731602430344,-13.562000155448914};
CHECK_CLOSE_COLLECTION(mctr, expected_mctr, 0.001);

Come su BOOST_CHECK_EQUAL_COLLECTIONS ?

BOOST_AUTO_TEST_CASE( test )
{
    int col1 [] = { 1, 2, 3, 4, 5, 6, 7 };
    int col2 [] = { 1, 2, 4, 4, 5, 7, 7 };

    BOOST_CHECK_EQUAL_COLLECTIONS( col1, col1+7, col2, col2+7 );
}

Esempio

Esecuzione caso 1 test ...

test.cpp (11): errore di "test": controllo {col1, col1 + 7} {== col2, col2 + 7} non è riuscita.

Non corrispondenza in una posizione 2: 3 = 4

Non corrispondenza in una posizione 5: 6 = 7

* 1 guasto rilevato in suite test "esempio"

Dal Boost 1.59 è molto più facile per confrontare le istanze std::vector. Vedere questa documentazione versione 1.63 (che è quasi uguale al riguardo a 1,59).

Per esempio, se si è dichiarato std::vector<int> a, b; è possibile scrivere

BOOST_TEST(a == b);

per ottenere un confronto molto di base. Il rovescio della medaglia è che in caso di fallimento Boost dice solo che a e b non sono gli stessi. Ma si ottiene più informazioni confrontando elemento-saggio che è possibile in modo elegante

BOOST_TEST(a == b, boost::test_tools::per_element() );

O se volete un confronto lessicografico si può fare

BOOST_TEST(a <= b, boost::test_tools::lexicographic() );

È possibile utilizzare BOOST_REQUIRE_EQUAL_COLLECTIONS con std::vector<T>, ma bisogna insegnare Boost.Test come stampare un std::vector quando si dispone di un vettore di vettori o di una mappa i cui valori sono vettori. Quando si dispone di una mappa, Boost.Test deve essere insegnato come stampare std::pair. Poiché non è possibile modificare la definizione di std::vector o std::pair, si deve fare questo in modo tale che l'operatore di inserimento stream che definito verrà utilizzato da Boost.Test senza essere parte della definizione della classe di std::vector. Inoltre, questa tecnica è utile se non si desidera aggiungere gli operatori di inserimento flusso per il sistema in prova solo per fare Boost.Test felice.

Ecco la ricetta per qualsiasi std::vector:

namespace boost
{

// teach Boost.Test how to print std::vector
template <typename T>
inline wrap_stringstream&
operator<<(wrap_stringstream& wrapped, std::vector<T> const& item)
{
    wrapped << '[';
    bool first = true;
    for (auto const& element : item) {
        wrapped << (!first ? "," : "") << element;
        first = false;
    }
    return wrapped << ']';
}

}

Questo formatta i vettori come [e1,e2,e3,...,eN] per un vettore con elementi N e funziona per qualsiasi numero di vettori annidati, ad esempio dove gli elementi del vettore sono anche vettori.

Ecco la ricetta simile per std::pair:

namespace boost
{

// teach Boost.Test how to print std::pair
template <typename K, typename V>
inline wrap_stringstream&
operator<<(wrap_stringstream& wrapped, std::pair<const K, V> const& item)
{
    return wrapped << '<' << item.first << ',' << item.second << '>';
}

}

BOOST_REQUIRE_EQUAL_COLLECTIONS vi dirà l'indice degli elementi non corrispondenti, così come i contenuti delle due collezioni, assumendo le due collezioni sono della stessa dimensione. Se sono di dimensioni diverse, allora questo è considerato un disadattamento e le dimensioni differenti vengono stampati.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top