2009-06-08 2 views
10

Sto tentando di avviare il test dell'unità. Sto osservando alcuni framework C++ e voglio provare Boost.Test. La documentazione sembra molto approfondita, ed è un po 'schiacciante, specialmente qualcuno che è nuovo ai test unitari. Quindi, ecco una situazione che voglio:Per iniziare a utilizzare Boost.Test

Diciamo che ho 2 classi, Foo e Bar. Voglio scrivere una suite di test per Foo e una suite di test per Bar, preferibilmente in file diversi. Voglio eseguire i test solo se eseguo il programma con un parametro della riga di comando. Quindi il mio main() dovrebbe essere simile:

int main(int argc, const char* argv[]) 
{ 
    if (argc == 1 && strcmp(argv[0], "-test") == 0) 
     run_all_tests(); 
    else 
     return program_main(argc, argv); 
} 

penso test_foo.cpp dovrebbe essere qualcosa di simile:

#include "foo.hpp" 
#define BOOST_TEST_MODULE Foo test 
#include <boost/test/unit_test.hpp> 

BOOST_AUTO_TEST_SUITE(Foo_Test) 

BOOST_AUTO_TEST_CASE(Foo1) 
{ 
    Foo f; 
    BOOST_CHECK(f.isValid()); 
} 

BOOST_AUTO_TEST_CASE(Foo2) 
{ 
    Foo f; 
    BOOST_CHECK(f.baz() == 5); 
} 

BOOST_AUTO_TEST_SUITE_END() 

Tuttavia, non so (1) quello che il comando effettivo per eseguire le prove è, e (2) come dire in realtà alla libreria che voglio eseguire OGNI test.

Quindi, chi ha esperienza con Boost.Test? Qualcuno può aiutare in modo dettagliato? Grazie mille.

risposta

3

BOOST.Il test è molto flessibile e probabilmente puoi fare quello che vuoi. Tuttavia, dal momento che dici di essere nuovo ai test unitari, probabilmente dovresti seguire la struttura di test unitaria standard.

Questo è per avere un progetto di test separato per ogni progetto che si sta testando. Quindi includere le fonti e le librerie necessarie per creare il progetto di test.

Questo è più pulito in quanto non ci sono logiche di test nel progetto principale che potrebbero essere eseguite accidentalmente ed è facile eseguire i test poiché hanno un proprio eseguibile. Questo approccio funziona anche per testare le librerie. Se segui questa struttura scoprirai che la maggior parte dei valori predefiniti BOOST.Test funzionano immediatamente e puoi solo preoccuparti di scrivere test e codice.

0

non c'è alcun test runner standalone come in NUnit

è sufficiente costruire i casi di test come una singola applicazione .exe (se siete su Windows) e lo si esegue

+0

Non capisco ... come si esegue il programma normalmente (senza test)? – rlbond

+0

in pratica il tuo test_foo.cpp dovrebbe essere creato come un singolo programma .exe e link alla tua libreria che contiene le classi Foo & Bar. Uno dei file header di boost.test definisce già la funzione principale, quindi non penso che ciò che hai proposto sia fattibile. – oscarkuo

+1

In realtà c'è. Si chiama console_test_runner. Anche se non è rilevante per il problema dell'OP poiché ha già un main. –

12

Nella tua test_foo.cpp, le macro aggiungere test suite e test case in in un elenco globale: master_testsuite, che è la radice di tutti i nodi di test . Hai solo bisogno di compilare tutti i file di test come test_foo.cpp, test_boo.cpp e un corridore, quindi collegarli tutti sul file eseguibile .

La funzione unit_test_main viene utilizzata per eseguire i test in master_testsuite.

boost::unit_test::unit_test_main(
    &init_unit_test, 
    argc, 
    argv 
) 

Sulla base della macro è stata definita prima di includere <boost/test/unit_test.h>, Boost.Test potrebbero già generare la funzione di main per te. [1] Il numero main generato ha semplicemente invocato unit_test_main con argc e argv in main. Si consiglia di utilizzare unit_test_main perché può elaborare alcuni argomenti della console, come run test by name.

Il primo argomento di unit_test_main è un hook. A seconda di BOOST_TEST_ALTERNATIVE_INIT_API, ha una definizione diversa.

#ifdef BOOST_TEST_ALTERNATIVE_INIT_API 
typedef bool  (*init_unit_test_func)(); 
#else 
typedef test_suite* (*init_unit_test_func)(int, char* []); 
#endif 

È possibile personalizzare il master_testsuite nel gancio. Nel secondo modulo , il valore restituito è il nuovo master suite di test.

[1] se BOOST_TEST_MAIN e BOOST_TEST_MAIN sono definiti, ma BOOST_TEST_NO_MAIN non è.

5

È possibile avviare i test da un comando di menu, ma non è così semplice e purtroppo non ben documentato. Ancora più triste: non è possibile passare il percorso in cui deve essere creato il file di registro. Ho dovuto aggiungere anch'io una tale opzione di comando. Purtroppo non l'ho ancora presentato. Il mio codice è simile al seguente:

#ifdef DEBUG 

#undef main 
#define BOOST_TEST_MAIN 
#include <boost/test/included/unit_test.hpp> 

int DoUnitTests() 

{ 
    char *args[] = {"", "--log_level=all", "--auto_start_dbg=yes"}; 

    bool result = ::boost::unit_test::unit_test_main(&init_unit_test_suite, sizeof(args)/sizeof(char*), args); 

    MessageDlog("Unittests result: %s", result ? "ERRORS in Unittests" : "Goooood!"); 
    return result; 
} 

#else 
int DoUnitTests() 

{ 
} 
#endif 
+0

no, non puoi iniziare 'char * []' con 'const char * []'. – Abyx

+0

Di cosa stai parlando? Si prega di essere più specifici. –

+0

Il tuo codice non verrà compilato. http://coliru.stacked-crooked.com/a/760be4eb168ba404 – Abyx

0

Prova questo script che ho scritto, che, dato un nome del programma e l'elenco delle classi genereranno gli scheletri Makefile, scheletro progetto e suite di test per ciascun/modulo di classe. Inoltre imposta tutto in modo che la suite di test per ogni classe possa essere eseguita singolarmente o come parte di una suite globale all-in-one.

Si chiama makeSimple ed è disponibile su sourceforge.