Różnice między wybraną wersją a wersją aktualną.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
|
boosttest [2008/04/16 02:00] twroniak |
boosttest [2008/04/16 23:00] (aktualna) twroniak |
||
|---|---|---|---|
| Linia 1: | Linia 1: | ||
| + | The acceptance test makes the customer satisfied that the\\ | ||
| + | software provides the business value that makes them willing\\ | ||
| + | to pay for it. The unit test makes the programmer satisfied\\ | ||
| + | that the software does what the programmer thinks it does.\\ | ||
| + | |||
| ===== Opis biblioteki ===== | ===== Opis biblioteki ===== | ||
| - | + | Biblioteka Boost.Test dostarcza programiście zestaw narzędzi do testowania tworzonego przez niego oprogramowania. Mechanizmy dostarczane przez bibliotekę umożliwiają tworzenie programów testujących, definiowanie przypadków testowych i grupowanie ich w zestawy testów oraz uruchamianie testów w monitorowanym środowisku. | |
| ==== Minimal testing facility ==== | ==== Minimal testing facility ==== | ||
| + | |||
| + | Minimal testing facility, jak sama nazwa wskazuje, stanowi minimum mechanizmów umożliwiających testowanie oprogramowania. Pierwsza wersja Boost.Test zawierała jedynie prezentowaną w tym podrozdziale funkcjonalność. Minimal testing facility dostarcza własną funkcję main(), która uruchamia funkcję test_main(dostarczaną przez użytkownika) w monitorowanym środowisku. Biblioteka dba o to, aby wszystkie parametry uruchomienia programu zostały również przekazane do funkcji test_main(). | ||
| <code cpp> | <code cpp> | ||
| Linia 34: | Linia 40: | ||
| int foo(3); | int foo(3); | ||
| + | |||
| + | //w monitorowanym srodowisku uzyskujemy dostep do makr testujacych o wiele mowiacych nazwach | ||
| + | //makro BOOST_REQUIRE przerywa testowanie w przypadku niespelnienia podanego mu warunku | ||
| BOOST_REQUIRE( foo == 3 ); | BOOST_REQUIRE( foo == 3 ); | ||
| + | //za pomoca tego makra powinny byc wiec testowane warunki, ktorych spelnienie jest krytyczne dla | ||
| + | //dalszego dzialania programu | ||
| + | |||
| + | //BOOST_CHECK wypisuje informacje o bledzie na standardowe wyjscie po zakonczeniu testow | ||
| BOOST_CHECK( square( foo ) == 9 ); | BOOST_CHECK( square( foo ) == 9 ); | ||
| BOOST_CHECK( square_err( foo ) == 9 ); | BOOST_CHECK( square_err( foo ) == 9 ); | ||
| Linia 65: | Linia 77: | ||
| ==== Program execution monitor ==== | ==== Program execution monitor ==== | ||
| + | |||
| + | Kolejnym udostępnianym przez bibliotekę mechanizmem jest Program execution monitor. Podobnie jak minimal testing facility tworzy on monitorowane środowisko uruchomieniowe, w którym uruchamiany jest program użytkownika. Po zakończeniu testów użytkownikowi przedstawiany jest raport z przeprowadzonych testów, zawierający informacje o testach, które się nie powiodły oraz o wyjątkach, które zostały zgłoszone, ale nie zostały obsłużone. | ||
| <code cpp> | <code cpp> | ||
| Linia 79: | Linia 93: | ||
| } | } | ||
| - | int cube( int arg ) | ||
| - | { | ||
| - | return arg*arg*arg; | ||
| - | } | ||
| - | |||
| - | int cube_err( int arg ) | ||
| - | { | ||
| - | return square_err( arg )*arg; | ||
| - | } | ||
| int cpp_main( int, char* [] ) //zmieniona nazwa !!!!!! | int cpp_main( int, char* [] ) //zmieniona nazwa !!!!!! | ||
| Linia 108: | Linia 113: | ||
| } | } | ||
| </code> | </code> | ||
| + | |||
| + | Program execution monitor posiada możliwość konfiguracji przez następujące zmienne środowiskowe: | ||
| + | * BOOST_TEST_CATCH_SYSTEM_ERRORS - pozwala wyłączyć przechwytywanie błędów systemowych, domyślnie ustawiona na "yes" | ||
| + | * BOOST_PRG_MON_CONFIRM - domyślnie ustawiona na "yes" powoduje wyświetlanie wiadomość potwierdzającą w przypadku pomyślnego zakończenia testów. | ||
| ==== Execution monitor ==== | ==== Execution monitor ==== | ||
| + | |||
| + | Execution monitor, czyli monitor wykonywania programu, jest jednym z niskopoziomowych elementów biblioteki Boost.Test, oraz stanowi bazę do implementacji pozostałych narzędzi przez nią oferowanych. Używany jako osobne narzędzie zapewnia monitorowane środowisko wykonywania programu oraz ujednoliconą obsługę błędów. Poniżej zaprezentowano jedną z ciekawszych jego cech, czyli rejestrowanie funkcji obsługujących własne wyjątki programisty. | ||
| <code cpp> | <code cpp> | ||
| Linia 189: | Linia 200: | ||
| ====Unit test framework ==== | ====Unit test framework ==== | ||
| + | |||
| + | Unit test framework jest narzędziem oferującym programiście prosty i przystępny sposób na testowanie jego programów. Jest moim zdaniem najprzydatniejszym elementem biblioteki. Umożliwia tworzenie przypadków testowych testujących zarówno niezwiązane funkcje, jak i metody klas. Przypadki testowe (test cases) można grupować w zestawy testowe (test suites) tak, aby np. testy metod jednej klasy były zgrupowane w jednym zestawie.\\ | ||
| + | \\ | ||
| + | |||
| + | Funkcja main nie jest dostarczana przez programistę, robi to za niego unit test framework. Programista musi zdefiniować funkcje o nagłówku boost::unit_test::test_suite* init_unit_test_suite ( int argc, char* argv[] ) | ||
| + | (argc i argv są parametrami wywołania, nie można ich pominąć przy deklaracji, można je zignorować pisząc init_unit_test_suite ( int, char* [] ) ). Zadaniem tej funkcji jest inicjalizacja drzewa testowego, wartością zwracaną powinien być master test suite, czyli zbiór wszystkich przypadków testowych. | ||
| + | |||
| + | <code cpp> | ||
| + | |||
| + | //naglowek zawierajacy Unit Test Framework | ||
| + | #include <boost/test/unit_test.hpp> | ||
| + | //naglowek zawierajacy BOOST_CHECK_CLOSE | ||
| + | #include <boost/test/floating_point_comparison.hpp> | ||
| + | #include <boost/shared_ptr.hpp> | ||
| + | using namespace boost::unit_test; | ||
| + | |||
| + | /****************************************************************************** | ||
| + | * wartosci zwracane przez Unit Test Framework po zakonczeniu testow: | ||
| + | * boost::exit_success - wszystkie testy zakonczone pomyslnie | ||
| + | * boost::exit_test_failure - wykryto niekytyczne bledy (nonfatal errors) lub | ||
| + | * nie powiodla sie inicjalizacja unit test suite | ||
| + | * boost::exit_exception_failure - pojawily sie bledy krytyczne lub niezlapane | ||
| + | * wyjatki | ||
| + | ******************************************************************************/ | ||
| + | |||
| + | // przypadki testowe mozna rejestrowac na kilka roznych sposobow,najprostszym z | ||
| + | // nich jest na pewno automatycznie rejestrowana funkcja niezwiazana z zadna klasa | ||
| + | // rejestrujemy ja za pomoca jednego z magicznych makr boost.test | ||
| + | // w nawiasie podawana jest nazwa przypadku testowego | ||
| + | BOOST_AUTO_TEST_CASE( auto_test_case ) | ||
| + | { | ||
| + | /* makro to automatycznie tworzy obiekt function_test_case oraz umieszcza go w | ||
| + | globalnym zestawie testowym. Testowana funkcja jest wlasnie niniejsza funkcja:) | ||
| + | */ | ||
| + | |||
| + | // w ramach kazdego przypadku testowego mozemy sprawdzic dowolna ilosc warunkow | ||
| + | int i = 666; | ||
| + | |||
| + | |||
| + | // zostanie wygenerowany komunikat 'error in "auto_test_case": check i == 667 failed [666 != 667]' | ||
| + | BOOST_CHECK_EQUAL( i, 667 ); | ||
| + | |||
| + | // tym razem wynik testu bedzie poprawny, nie zotanie wygenerowany zaden komunikat | ||
| + | BOOST_CHECK( i == 666 ); | ||
| + | } | ||
| + | |||
| + | // automatycznie rejestrowane przypadki testowe mozna grupowac w zetawy testowe | ||
| + | BOOST_AUTO_TEST_SUITE( auto_test_suite ) | ||
| + | |||
| + | // ten przypadek testowy bedzie nalezal do auto_test_suite, a nie do globalnego zestawu | ||
| + | BOOST_AUTO_TEST_CASE( nonglobal_test ) | ||
| + | { | ||
| + | BOOST_CHECK_MESSAGE( 2+2 == 5, "ten komunikat bedzie wypisany zamiast zwyklego komunikatu o bledzie"); | ||
| + | |||
| + | double x = 1.000000, y = 1.000001; | ||
| + | double epsilon = 1e-6; | ||
| + | |||
| + | //sprawdzenie, czy dwie liczby roznia sie od siebie o nie wiecej niz zadana wartosc | ||
| + | BOOST_CHECK_CLOSE( x, y, epsilon ); | ||
| + | |||
| + | } | ||
| + | |||
| + | // automatyczne zestawy testowe mozna zagniezdzac | ||
| + | BOOST_AUTO_TEST_SUITE( internal_test_suite ) | ||
| + | |||
| + | BOOST_AUTO_TEST_CASE( internal_suite_test_case ) | ||
| + | { | ||
| + | |||
| + | BOOST_ERROR( "internal_suite_test_case_error" ); | ||
| + | |||
| + | } | ||
| + | |||
| + | BOOST_AUTO_TEST_SUITE_END() //zakonczenie internal_test_suite | ||
| + | |||
| + | BOOST_AUTO_TEST_SUITE_END() //zakonczenie auto_test_suite | ||
| + | |||
| + | // mozemy definiowac niezwiazane funkcje testujace, ktore nastepnie beda dodane zamienione | ||
| + | // na przypadki testowe w funkcji init_unit_test_suite | ||
| + | void free_test_function() | ||
| + | { | ||
| + | // wypisuje 'unknown location(0): fatal error in "free_test_function": memory access violation | ||
| + | // nazwapliku.cpp(numerLinii): last checkpoint' | ||
| + | int* p = (int*)0x01; | ||
| + | BOOST_CHECKPOINT( "Za chwile wystapi naruszenie ochrony pamieci" ); | ||
| + | //BOOST_CHECK( *p == 0 ); //wywolanie tej linijki spowoduje wystapienie fatalerror | ||
| + | // co z kolei spowoduje zakonczenie testow i wyjscie z programu | ||
| + | |||
| + | BOOST_CHECK( 2 == 1 ); | ||
| + | } | ||
| + | |||
| + | class KlasaTestujaca | ||
| + | { | ||
| + | int i; | ||
| + | public: | ||
| + | explicit KlasaTestujaca(int i_): i(i_) {} | ||
| + | |||
| + | void class_test_case() | ||
| + | { | ||
| + | BOOST_CHECK(2 == 1); | ||
| + | } | ||
| + | }; | ||
| + | //____________________________________________________________________________// | ||
| + | |||
| + | |||
| + | test_suite* | ||
| + | init_unit_test_suite( int, char* [] ) { | ||
| + | |||
| + | framework::master_test_suite().p_name.value = "Przykladowe test_suite"; | ||
| + | |||
| + | //jesli nie korzystamy z globalnego zestawu testow, mozemy definiowac wlasne | ||
| + | //za pomoca makra o nastepujacej skladni | ||
| + | //test_suite* test= BOOST_TEST_SUITE( "nazwa zestawu testow" ); | ||
| + | //wywolujac metode add(tak jak ponizej) mozemy dodawac przypadki testowe | ||
| + | //oraz nowe zestawy testow, ukladajac je w drzewiasta strukture | ||
| + | |||
| + | |||
| + | framework::master_test_suite().add( BOOST_TEST_CASE( &free_test_function ), 3 ); | ||
| + | boost::shared_ptr<KlasaTestujaca> instance( new KlasaTestujaca(0) ); | ||
| + | framework::master_test_suite().add( BOOST_CLASS_TEST_CASE( &KlasaTestujaca::class_test_case, instance ) ); | ||
| + | |||
| + | return 0; | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | Jak łatwo zauważyć biblioteka ta w znacznym stopniu polega na prostych makrach opakowujących szablony. Skutkuje to niestety znacznym wydłużeniem kompilacji, która na słabszych komputerach (takich jak np. komputer autora:) ) może trwać na prawdę długo. Elegancję tak frywolnego użycia tak dużej ilości makr pozostawiam do oceny czytelnikowi. | ||
| + | |||