[B]asic module for [unit] program testing:
|
00001 // BUnit.h (C) 2008 adolfo@di-mare.com 00002 00003 /* 00004 THIS IS FREE SOFWTWARE. 00005 - Use at your own risk; acknowledge authorship, please. 00006 - You can never blame the author for your use of this software. 00007 - Released to the world under LGPLv3: 00008 http://www.gnu.org/licenses/lgpl-3.0.html 00009 ESTE PROGRAMA ES LIBRE. 00010 - Uselo baja su propia responsabilidad; reconozca la autoría, por favor. 00011 - Usted nunca podrá culpar al autor por su propio uso de este software. 00012 - Entregado al mundo bajo LGPLv3: 00013 http://www.gnu.org/licenses/lgpl-3.0.html 00014 */ 00015 /* 00016 Version 0: No TestSuite<> 00017 Version 1: English Doxygen 00018 Version 2: English+Spanish Doxygen 00019 */ 00020 00021 #ifdef English_dox 00022 /** \file BUnit.h 00023 \brief [B]asic module for [unit] program testing. 00024 00025 \author Adolfo Di Mare <adolfo@di-mare.com> 00026 \date 2008 00027 */ 00028 #endif 00029 #ifdef Spanish_dox 00030 /** \file BUnit.h 00031 \brief Módulo [B]ásico para prueba [unit]aria de programas. 00032 00033 \author Adolfo Di Mare <adolfo@di-mare.com> 00034 \date 2008 00035 */ 00036 #endif 00037 00038 #ifdef English_dox 00039 /// Doxygen English documentation. 00040 #define English_dox "Doxygen English documentation" 00041 /// \def English_dox ///< Marks English documentation blocks. 00042 /// \def BUnit_h ///< Avoids multiple inclusion. 00043 #endif 00044 #ifdef Spanish_dox 00045 /// Documentación en español. 00046 #define Spanish_dox "Documentación en español" 00047 /// \def Spanish_dox ///< Macro usado para que Doxygen genere documentación 00048 /// \def BUnit_h ///< Evita la inclusión múltiple. 00049 #endif 00050 00051 #ifndef BUnit_h 00052 #define BUnit_h // avoid multiple inclusion 00053 00054 #include <list> // std::list 00055 #include <string> // class std::string 00056 #include <sstream> // class basic_ostringstream<T,Ch> 00057 #include <cstring> // memcpy()+strlen() 00058 #include <typeinfo> // class std::type_info ==> char* typeid().name(); 00059 #include <algorithm> // find() 00060 00061 namespace std {} // using namespace std; 00062 00063 /// Escuela de Ciencias de la Computación e Informática. 00064 /// \see http://www.ecci.ucr.ac.cr 00065 namespace ECCI { } 00066 00067 // Private class to hold test cases that didn´t succeed. 00068 class TestCaseFailure { 00069 private: 00070 const char * m_fname; // file where the failure ocurred 00071 int m_lineno; // line for the failure 00072 const char * m_label; // descriptive message for the failure 00073 bool m_destroy_label; // true when "m_label" requires destruction 00074 private: 00075 TestCaseFailure() : // almost never used 00076 m_fname(""), m_lineno(0), m_label(""), m_destroy_label(false) 00077 { } // always sets "m_destroy_label" to "false" 00078 TestCaseFailure(const char * fname, int line, const char * label, bool destroy ) 00079 : m_fname(fname), m_lineno(line), m_label(label), m_destroy_label(destroy) 00080 { } 00081 public: 00082 ~TestCaseFailure() { if (m_destroy_label) { delete [] m_label; } } 00083 TestCaseFailure( const TestCaseFailure& o ) { 00084 m_fname = o.m_fname; m_lineno = o.m_lineno; m_label = o.m_label; 00085 m_destroy_label = o.m_destroy_label; 00086 // avoid double destruction of "m_label" 00087 const_cast<TestCaseFailure*>(&o)->m_destroy_label = false; 00088 // const_cast<bool>(o.m_destroy_label) = false; // won't compile 00089 } 00090 void operator = ( TestCaseFailure& o ) { 00091 m_fname = o.m_fname; m_lineno = o.m_lineno; m_label = o.m_label; 00092 m_destroy_label = o.m_destroy_label; 00093 o.m_destroy_label = false; // evita doble destrucción de "m_label" 00094 } 00095 template <class TestCase> friend void do_toXML( 00096 const TestCase * tc , std::basic_ostringstream<char> & ost ); 00097 template <class TestCase> friend void do_toString( 00098 const TestCase * tc , std::basic_ostringstream<char> & ost ); 00099 #ifdef English_dox 00100 /// Test case. 00101 #endif 00102 #ifdef Spanish_dox 00103 /// Caso de prueba. 00104 #endif 00105 friend class TestCase; 00106 }; // TestCaseFailure 00107 00108 00109 // Abstract base class for every test case ==> 00110 // - It's always mandatory to reimplement \c TestCase::run(). 00111 class TestCase { 00112 protected: 00113 int m_pass; // number successful tests 00114 int m_failure; // number of non successful tests [broken assert_XXX()] 00115 const char * m_name; // name for the test case 00116 bool m_test_suite_destroy; // true means destroy from dynamic memory 00117 std::list<TestCaseFailure> m_failureList; // container for al non successful tests 00118 public: 00119 TestCase(const char * name=0); 00120 virtual ~TestCase() { } 00121 virtual bool run() = 0; // must implement in derived class 00122 void runBare(); 00123 bool Run() { return run(); } // same as run() 00124 bool runTest() { return run(); } 00125 virtual void setUp(); 00126 virtual void tearDown(); 00127 int countTestCases() const { return 1; } // more than 1 for TestSuite<> 00128 // errorCount() == 0 ==> "error" means "wrong exception" 00129 int runCount() const { return successCount()+failureCount()+errorCount(); } 00130 virtual int failureCount() const { return m_failure; } 00131 int errorCount() const { return 0; } 00132 virtual int successCount() const { return m_pass; } 00133 // true when all runs have been a success 00134 bool wasSuccessful() const { return successCount() == runCount(); } 00135 virtual void reset(); // resets al counter back to 0 00136 public: 00137 std::string getName() const; 00138 void setName( const char * name=0 ); 00139 virtual const std::string toString() const; 00140 virtual const std::string summary() const; 00141 virtual const std::string toXML() const; 00142 const std::string report() const { return summary() + '\n' + toString(); } 00143 const std::string failureString() const { return toString(); } 00144 template <class T> static std::string toString( const T & val ); 00145 protected: 00146 void recordSuccess() { ++m_pass; } // record another successful test 00147 void recordFailure( // (char*) version 00148 const char* label, const char* fname, int lineno, 00149 bool must_copy=false ); 00150 void recordFailure( // std::string version 00151 const std::string& label, const char* fname, int lineno ); 00152 void testThis( // (char*) version ==> don't destroy label 00153 bool cond, const char* label, const char* fname, long lineno, 00154 bool must_copy=false ); 00155 void testThis( // string<> version ==> create copy of "label" in dynamic memory 00156 bool cond, const std::string& label, const char* fname, long lineno ); 00157 template <class TestCase> friend 00158 void do_toXML( const TestCase * tc , std::basic_ostringstream<char> & ost ); 00159 template <class TestCase> friend 00160 void do_toString( const TestCase * tc , std::basic_ostringstream<char> & ost ); 00161 template <class TestCase> friend class TestSuite; ///< Colección de pruebas. 00162 int nPass() const { return m_pass; } // Deprecated: it's here for 00163 int nError() const { return m_failure; } // compatibility with Allison's work 00164 private: 00165 virtual bool iAmTestSuite() const { return false; } // I am NOT a TestSuite<> 00166 TestCase(const TestCase&); // trick to prevent copy on init 00167 TestCase& operator=(const TestCase&); // trick to prevent copying 00168 #ifdef English_dox 00169 /// Test case class for \c BUnit.h 00170 #endif 00171 #ifdef Spanish_dox 00172 /// Clase de prueba para \c BUnit.h 00173 #endif 00174 friend class test_BUnit; 00175 }; // TestCase 00176 00177 #ifdef Spanish_dox 00178 /// Sinónimo de \c TestCase. 00179 #endif 00180 #ifdef English_dox 00181 /// Synonym for \c TestCase. 00182 #endif 00183 typedef TestCase TestCase_is_base_for_TestSuite; 00184 00185 // Test collection. 00186 template <class TestCase> 00187 class TestSuite : public TestCase_is_base_for_TestSuite { 00188 public: 00189 typedef std::list<TestCase_is_base_for_TestSuite*> container_type; 00190 typedef container_type::iterator iterator; 00191 typedef const container_type::iterator cons_iterator; 00192 typedef const container_type const_container_type; 00193 private: 00194 container_type m_allTest; // holds [pointers to] failed tests 00195 public: 00196 TestSuite(const char * name=0): TestCase(name), m_allTest() { } 00197 virtual ~TestSuite(); 00198 bool addTest(TestCase& T); 00199 bool addTest(TestCase* T); 00200 void addSuite( TestSuite& SSS ); 00201 bool run(); // implemented: TestSuite<> is not an abstract class 00202 void runBare(); 00203 int countTestCases() const { return int(m_allTest.size()); } 00204 int failureCount() const; 00205 int successCount() const; 00206 void reset(); 00207 const_container_type& allTests() const { return m_allTest; } 00208 const std::string toString() const; 00209 const std::string summary() const; 00210 const std::string toXML() const; 00211 private: 00212 bool iAmTestSuite() const { return true; } 00213 TestSuite(const TestSuite& DONTcopy); 00214 TestSuite& operator=(const TestSuite& DONTcopy); // forbid copying 00215 }; // TestSuite 00216 00217 /************************\ 00218 ************************** 00219 ** ** 00220 ** BUnit.h ** 00221 ** ** 00222 ************************** 00223 \************************/ 00224 00225 #ifdef English_dox 00226 /// Doxygen English documentation. 00227 #define English_dox "Doxygen English documentation" 00228 /// \def English_dox ///< Marks English documentation blocks. 00229 #endif 00230 #ifdef Spanish_dox 00231 /// Documentación en español. 00232 #define Spanish_dox "Documentación en español" 00233 /// \def Spanish_dox ///< Macro usado para que Doxygen genere documentación 00234 #endif 00235 00236 #ifdef English_dox 00237 /** \mainpage 00238 00239 \section sec-01 [B]asic module for [unit] program testing. 00240 00241 Header file \c BUnit.h supports writing modules for unit program testing. 00242 The model used for this implementation is similar to that described in 00243 the article "The Simplest Automated Unit Test Framework That Could 00244 Possibly Work "by Chuck Allison, which you can get here: 00245 - http://www.stickyminds.com/getfile.asp?ot=XML&id=3129&fn=XDD3129filelistfilename1.pdf 00246 - http://www.google.com/search?num=100&as_q=Simplest+Unit+Test+Allison 00247 - http://search.yahoo.com/search?n=100&p=Simplest+Unit+Test+Allison 00248 00249 - To simplify to a minimum the task of writing test cases, the full 00250 implementation of \c BUnit is contained within the single header 00251 file \c BUnit.h, so testing requieres only this directive: 00252 - <strong>\#include "BUnit.h"</strong> 00253 - This framework is similar to JUnit, because it is presumed that 00254 in the future students will use Java as their primary language 00255 to develop programs (as C++ is used only for deep training in 00256 programming techniques). 00257 \see http://search.yahoo.com/search?n=100&p=JUnit+Java 00258 - As C++ does not have a mechanism similar to Java's "reflection", 00259 for each failed test the exact test condition is recorded 00260 using an invocation to macro \c BUnit_TEST() that also records 00261 the filename \c __FILE__ and the line \c __LINE__ for that test. 00262 \see http://search.yahoo.com/search?n=100&p=reflection+Java 00263 - In JUnit class \c TestCase is a subclass of \c Assert; in BUnit no 00264 \c Assert class exist but to maintain compatibility with JUnit similar 00265 functionality is provided with macros whose names begin with "assert". 00266 \see http://search.yahoo.com/search?n=100&p=JUnit+Java+Assert+method 00267 - To simplify this framework no difference is made between a test that 00268 is not successfull and one that didn´t succeed because the correct 00269 exception was not raised. This is a contrast with JUnit where an 00270 "error" is a test case that raised the wrong exception. This 00271 explains why \c TestCase::errorCount() always returns zero \c 0. 00272 \code 00273 // Failure vs Error in JUnit 00274 public void test_Fail () { 00275 try { 00276 new ArrayList(10).get( 11 ); 00277 fail("Error if IndexOutOfBoundsException is not thrown" ); // error 00278 } 00279 catch (IndexOutOfBoundsException success) { } // Ok 00280 } 00281 public void test_Failure() { 00282 assertTrue( 1 == 2 ); // failure 00283 } 00284 \endcode 00285 - In \c BUnit.h no difference is made between "failures" and "errors". 00286 - En \c JUnit an "error" means that the wrong exception was raised. 00287 - En \c JUnit a "failure" means that an assertion was false. 00288 - \see http://osdir.com/ml/java.junit.user/2002-06/msg00114.html 00289 - \see http://search.yahoo.com/search?n=100&p=junit+difference+failure+error 00290 - In JUnit, what's the difference between a failure and an error? 00291 - Assertions are used to check for the possibility of failures, 00292 therefore failures are anticipated with invokations similar to \c assertTrue(). 00293 - Errors are unanticipated problems resulting in uncaught exceptions 00294 being propagated from a JUnit test method. 00295 - \see http://www.cs.waikato.ac.nz/~bernhard/314/junit3.8.1/doc/faq/faq.htm#tests_9 00296 - \see http://www.cs.wm.edu/~noonan/junit/doc/faq/faq.htm#tests_9 00297 00298 \dontinclude test_BUnit.cpp 00299 \skipline test::Allison() 00300 \until }} 00301 \see test_BUnit::test_Allison() 00302 */ 00303 #endif 00304 #ifdef Spanish_dox 00305 /** \mainpage 00306 00307 \section sec-01 Módulo [B]ásico para prueba [unit]aria de programas. 00308 00309 El archivo de encabezado \c BUnit.h apoya la escritura de módulos de prueba de 00310 unitaria programas. El modelo que se usa para esta implementación es 00311 similar al expuesto en este artículo "The Simplest Automated Unit 00312 Test Framework That Could Possibly Work" de Chuck Allison, que se 00313 puede obtener aquí: 00314 - http://www.stickyminds.com/getfile.asp?ot=XML&id=3129&fn=XDD3129filelistfilename1.pdf 00315 - http://www.google.com/search?num=100&as_q=Simplest+Unit+Test+Allison 00316 - http://search.yahoo.com/search?n=100&p=Simplest+Unit+Test+Allison 00317 00318 - Para simplificar al mínimo la tarea de programar los casos de prueba, 00319 la implementación completa de \c BUnit está contenida en el archivo 00320 de encabezado \c BUnit.h, por lo que para hacer pruebas basta poner 00321 esta directiva: 00322 - <strong>\#include "BUnit.h"</strong> 00323 - Este marco de pruebas es similar a JUnit, pues se presume que en 00324 el futuro los estudiantes usarán Java como su lenguaje principal 00325 para desarrollo de programas (pues usan C++ sólo para adiestrarse 00326 profundamente en técnicas de programación). 00327 \see http://search.yahoo.com/search?n=100&p=JUnit+Java 00328 - Como el lenguaje C++ no tiene un mecanismo similar al de "reflexión" 00329 de Java, en cada prueba fallida se registra la condición de prueba 00330 exacta, obtenida a través de una invocación de la macro \c BUnit_TEST() 00331 que registra el nombre del archivo \c __FILE__ y el renglón \c __LINE__ 00332 de la prueba. 00333 \see http://search.yahoo.com/search?n=100&p=reflection+Java 00334 - En JUnit la clase \c TestCase es una subclase de \c Assert; en BUnit no 00335 existe la clase \c Assert pero para mantener compatibilidad con JUnit 00336 sí se provée funcionalidad similar usando macros cuyos nombres comienzan 00337 con "assert". 00338 \see http://search.yahoo.com/search?n=100&p=JUnit+Java+Assert+method 00339 - Para simplificar este marco de pruebas no se usa la clase \c TestResult 00340 que sirve para acumular resultados de las pruebas. En su lugar, se puede 00341 obtener una hilera enorme \c std::string que contiene el registro de 00342 todas las pruebas que no tuvieron éxito invocando el método 00343 \c TestCase::toString() o \c TestCase::toXML(). 00344 - Para simplificar esta plataforma de pruebas no se hace diferencia entre 00345 un caso de prueba de prueba no existoso y uno que no tiene éxito porque no 00346 se ha levantado la excepción adecuada. Esto contrasta con JUnit, que 00347 llama "error" a un caso de prueba que ha levantado la excepción equivocada. 00348 Por eso \c TestCase::errorCount() siempre retorna cero \c 0. 00349 \code 00350 // Falla vs Error en JUnit 00351 public void test_Error() { 00352 try { 00353 new ArrayList(10).get( 11 ); 00354 fail("Error si no tira IndexOutOfBoundsException" ); // error 00355 } 00356 catch (IndexOutOfBoundsException success) { } // Ok 00357 } 00358 public void test_Failure() { 00359 assertTrue( 1 == 2 ); // falla 00360 } 00361 \endcode 00362 - En \c BUnit.h no se hace diferencia entre "fallas" y "errores". 00363 - En \c JUnit un "error" se produce cuando no se levanta la excepción adecuada. 00364 - En \c JUnit una "falla" se produce cuando una aserción resulta falsa. 00365 - \see http://osdir.com/ml/java.junit.user/2002-06/msg00114.html 00366 - \see http://www.cs.waikato.ac.nz/~bernhard/314/junit3.8.1/doc/faq/faq.htm#tests_9 00367 - \see http://search.yahoo.com/search?n=100&p=junit+difference+failure+error 00368 - In JUnit, ¿cuál es la diferencia entre fallas y errores? 00369 - Las aseveraciones son usadas para verificar si existen fallas, y por eso las 00370 fallas son previstas con invocaciones similares a \c assertTrue(). 00371 - Los errores son problemas no previstos que resultan de excepciones no captadas 00372 por los método de prueba JUnit. 00373 - \see http://www.cs.waikato.ac.nz/~bernhard/314/junit3.8.1/doc/faq/faq.htm#tests_9 00374 - \see http://www.cs.wm.edu/~noonan/junit/doc/faq/faq.htm#tests_9 00375 00376 \dontinclude test_BUnit.cpp 00377 \skipline test::Allison() 00378 \until }} 00379 \see test_BUnit::test_Allison() 00380 */ 00381 #endif 00382 00383 #ifdef Spanish_dox 00384 // using namespace std; 00385 /// Definido por la biblioteca C++ estándar. 00386 namespace std {} // It's here for Doxygen to document it 00387 #endif 00388 #ifdef English_dox 00389 // using namespace std; 00390 /// Defined by the C++ estándar library. 00391 namespace std {} // Está acá para que Doxygen lo documente 00392 #endif 00393 00394 /// Escuela de Ciencias de la Computación e Informática. 00395 /// \see http://www.ecci.ucr.ac.cr 00396 namespace ECCI { } 00397 00398 /************************\ 00399 ************************** 00400 ** ** 00401 ** TestCaseFailure ** 00402 ** ** 00403 ************************** 00404 \************************/ 00405 00406 #ifdef English_dox 00407 /** \class TestCaseFailure 00408 \brief Private class to hold test cases that didn´t succeed. 00409 */ 00410 /** \var const char * TestCaseFailure::m_fname; 00411 \brief Name of the file where the failure was produced. 00412 */ 00413 /** \var int TestCaseFailure::m_lineno; 00414 \brief Line number in the file where the failure was produced. 00415 */ 00416 /** \var const char * TestCaseFailure::m_label; 00417 \brief Descriptive message for the failure. 00418 */ 00419 /** \var bool TestCaseFailure::m_destroy_label; 00420 \brief Holds \c "true" if the destructor should return the dynamic memory for \c m_label. 00421 */ 00422 /** \fn TestCaseFailure::TestCaseFailure(); 00423 \brief Default constructor. 00424 */ 00425 /** \fn TestCaseFailure::TestCaseFailure(const char * fname, int line, const char * label, bool destroy ); 00426 \brief Private constructor that can set \c m_label to \c true. 00427 */ 00428 #endif 00429 #ifdef Spanish_dox 00430 /** \class TestCaseFailure 00431 \brief Clase privada que contiene los datos de cada prueba no exitosa. 00432 */ 00433 /** \var const char * TestCaseFailure::m_fname; 00434 \brief Nombre del archivo en donde se produjo el error. 00435 */ 00436 /** \var int TestCaseFailure::m_lineno; 00437 \brief Número de línea del archivo en donde se produjo el error. 00438 */ 00439 /** \var const char * TestCaseFailure::m_label; 00440 \brief Mensaje descriptivo del error. 00441 */ 00442 /** \var bool TestCaseFailure::m_destroy_label; 00443 \brief Contiene \c "true" si el destructor debe retornar la memoria dinámica de \c m_label. 00444 */ 00445 /** \fn TestCaseFailure::TestCaseFailure(); 00446 \brief Constructor por defecto. 00447 */ 00448 /** \fn TestCaseFailure::TestCaseFailure(const char * fname, int line, const char * label, bool destroy ); 00449 \brief Constructor Privado que puede inicializar \c m_label en \c true. 00450 */ 00451 #endif 00452 00453 #ifdef English_dox 00454 /** \fn TestCaseFailure::~TestCaseFailure(); 00455 \brief Destructor. 00456 */ 00457 /** \fn TestCaseFailure::TestCaseFailure( const TestCaseFailure& o ); 00458 \brief Copy constructor. 00459 */ 00460 /** \fn void TestCaseFailure::operator = ( TestCaseFailure& o ); 00461 \brief Copy operator used to insert into contanier. 00462 */ 00463 #endif 00464 00465 #ifdef Spanish_dox 00466 /** \fn TestCaseFailure::~TestCaseFailure() 00467 \brief Destructor. 00468 */ 00469 /** \fn TestCaseFailure::TestCaseFailure( const TestCaseFailure& o ); 00470 \brief Constructor de copia. 00471 */ 00472 /** \fn void TestCaseFailure::operator = ( TestCaseFailure& o ) 00473 \brief Copiador usado al insertar en el contenedor. 00474 */ 00475 #endif 00476 00477 /************************\ 00478 ************************** 00479 ** ** 00480 ** TestCase ** 00481 ** ** 00482 ************************** 00483 \************************/ 00484 00485 #ifdef English_dox 00486 /** \class TestCase 00487 \brief Every test case is an instance derived from this abstract class. 00488 - It's always mandatory to reimplement \c TestCase::run(). 00489 */ 00490 /** \fn int TestCase::m_pass; 00491 \brief Number of successful tests. 00492 */ 00493 /** \fn int TestCase::m_failure; 00494 \brief Number of test that produced failed. 00495 */ 00496 /** \fn const char * TestCase::m_name; 00497 \brief Test case name. 00498 */ 00499 /** \fn bool TestCase::m_test_suite_destroy; 00500 \brief Holds \c "true" if the test case is stored in dynamic memory. 00501 */ 00502 /** \fn std::list<TestCaseFailure> TestCase::m_failureList; 00503 \brief Container where test cases that produced failures are stored. 00504 */ 00505 #endif 00506 00507 #ifdef Spanish_dox 00508 /** \class TestCase 00509 \brief Cada caso de prueba es una instancia derivada de esta clase abstracta. 00510 - Siempre es obligatorio reimplementar \c TestCase::run(). 00511 */ 00512 /** \fn int TestCase::m_pass; 00513 \brief Cantidad de pruebas exitosas. 00514 */ 00515 /** \fn int TestCase::m_failure; 00516 \brief Cantidad de pruebas que han fallado. 00517 */ 00518 /** \fn const char * TestCase::m_name; 00519 \brief Nombre del caso de prueba. 00520 */ 00521 /** \fn bool TestCase::m_test_suite_destroy; 00522 \brief Contiene \c "true" si la prueba está almacenada en memoria dinámica. 00523 */ 00524 /** \fn std::list<TestCaseFailure> TestCase::m_failureList; 00525 \brief Contenedor para almacenar las pruebas que han producido fallas. 00526 */ 00527 #endif 00528 00529 #ifdef English_dox 00530 /** \fn virtual TestCase::~TestCase(); 00531 \brief Destructor. 00532 */ 00533 /** \fn virtual bool TestCase::run() = 0; 00534 \brief <strong>[virtual]</strong> ==> Executes test and returns \c "false" if not successful. 00535 <strong>[***]</strong> It is always mandatory to redefine method \c run(). 00536 \see runBare(). 00537 */ 00538 /** \fn bool TestCase::Run(); 00539 \brief Synonym for \c run(). 00540 */ 00541 /** \fn bool TestCase::runTest(); 00542 \brief Synonym for \c run(). 00543 */ 00544 /** \fn int TestCase::countTestCases() const; 00545 \brief 1 == Number of test cases. 00546 The value returned always is one \c 1 because class \c TestCase 00547 represents a single test case. For the container \c TestSuite<> 00548 the value returned can be bigger than \c 1. 00549 - A "test case" is a class, derived from class \c TestCase. 00550 - A "test run" gets counted when either a specific test succeeds or fails. 00551 - A "test run" gets counted when protected method TestCase::testThis() is 00552 executed, either directly or through any BUnit \c "assert()" macro, as 00553 \c assertTrue(), \c fail_Msg(), \c assertEquals_Delta(), or others like 00554 \c BUnit_SUCCESS() or \c BUnit_TEST(). 00555 - A "test case" ussually has many "test runs". A collection of "test cases" 00556 resided within an instance derived from class \c TestSuite<>. 00557 */ 00558 /** \fn int TestCase::runCount() const; 00559 \brief Number of test runs. 00560 - Synonym for <code>successCount()+failureCount()+errorCount()</code>. 00561 \see reset(). 00562 */ 00563 /** \fn virtual int TestCase::failureCount() const; 00564 \brief Number of test runs that failed. \see reset(). 00565 */ 00566 /** \fn int TestCase::errorCount() const; 00567 \brief Always returns \c 0 (cero): "Number of errors". 00568 - BUnit does not maintain separate counts for "errors" and "failures". 00569 \see http://osdir.com/ml/java.junit.user/2002-06/msg00114.html 00570 */ 00571 /** \fn virtual int TestCase::successCount() const; 00572 \brief Number of successful test runs. \see reset(). 00573 */ 00574 /** \fn bool TestCase::wasSuccessful() const; 00575 \brief Returns \c "true" when all test runs where successful. 00576 - Synonym for <code>(successCount() == runCount())</code> 00577 */ 00578 /** \fn std::string TestCase::getName() const; 00579 \brief Gets the test case name. \see setName(). 00580 */ 00581 /** \fn const std::string TestCase::report() const; 00582 \brief Returns string \c summary() followed by \c toString(). 00583 */ 00584 /** \fn const std::string TestCase::failureString() const; 00585 \brief Synonym for \c toString(). 00586 */ 00587 /** \fn void TestCase::recordSuccess(); 00588 \brief Records the test run as a success. 00589 */ 00590 /** \fn int TestCase::nPass() const; 00591 \brief Synonym for \c successCount() [OBSOLETE]. \deprecated 00592 */ 00593 /** \fn int TestCase::nError() const; 00594 \brief Synonym for \c failureCount() [OBSOLETE]. \deprecated 00595 */ 00596 /** \fn virtual bool TestCase::iAmTestSuite() const; 00597 \brief Returns \c false for \c TestCase. 00598 */ 00599 /** \fn TestCase::TestCase(const TestCase&); 00600 \brief This \c "private" declaration forbids test case copying. 00601 */ 00602 /** \fn TestCase& TestCase::operator=(const TestCase&); 00603 \brief This \c "private" declaration forbids test case copying. 00604 */ 00605 #endif 00606 #ifdef Spanish_dox 00607 /** \fn virtual TestCase::~TestCase(); 00608 \brief Destructor. 00609 */ 00610 /** \fn virtual bool TestCase::run() = 0; 00611 \brief <strong>[virtual]</strong> ==> Ejecuta la prueba y retorna \c "false" si produce error. 00612 <strong>[***]</strong> Siempre es necesario redefinir el método \c run(). 00613 \see runBare(). 00614 */ 00615 /** \fn bool TestCase::Run(); 00616 \brief Sinónimo de \c run(). 00617 */ 00618 /** \fn bool TestCase::runTest(); 00619 \brief Sinónimo de \c run(). 00620 */ 00621 /** \fn int TestCase::countTestCases() const; 00622 \brief 1 == Cantidad de casos de prueba. 00623 El valor retornado siempre es uno \c 1 porque la clase \c TestCase 00624 representa un único caso de pruebas. Para el contenedor 00625 \c TestSuite<> el valor retornado puede ser mayor a \c 1. 00626 - Un "caso de prueba" es una clase derivada de la clase \c TestCase. 00627 - Una "prueba" se cuenta cuando tiene éxito o fracasa. 00628 - Una "prueba" se cuenta cuando el método protegido TestCase::testThis() es 00629 ejecutado, ya sea directamente o a través de cualquiera de los macros 00630 \c "assert()" de BUnit, como lo son \c assertTrue(), \c fail_Msg(), 00631 \c assertEquals_Delta(), u otros como \c BUnit_SUCCESS() or \c BUnit_TEST(). 00632 - Un "caso de prueba" generalmente incluye muchas "pruebas". Una colección de 00633 "casos de prueba" reside en una instancia derivada de la clase \c TestSuite<>. 00634 */ 00635 /** \fn int TestCase::runCount() const; 00636 \brief Cantidad total de pruebas realizadas. 00637 - Sinónimo de <code>successCount()+failureCount()+errorCount()</code>. 00638 \see reset(). 00639 */ 00640 /** \fn virtual int TestCase::failureCount() const; 00641 \brief Cantidad de pruebas que fallaron. \see reset(). 00642 */ 00643 /** \fn int TestCase::errorCount() const; 00644 \brief Siempre retorna \c 0 (cero): "Cantidad de errores". 00645 - BUnit no se contabilizan aparte los "errores" de las "fallas". 00646 \see http://osdir.com/ml/java.junit.user/2002-06/msg00114.html 00647 */ 00648 /** \fn virtual int TestCase::successCount() const; 00649 \brief Cantidad de pruebas exitosas. \see reset(). 00650 */ 00651 /** \fn bool TestCase::wasSuccessful() const; 00652 \brief Retorna \c "true" si todas las pruebas han sido exitosas. 00653 - Sinónimo de <code>(successCount() == runCount())</code> 00654 */ 00655 /** \fn std::string TestCase::getName() const; 00656 \brief Obtiene el nombre de la prueba. \see setName(). 00657 */ 00658 /** \fn const std::string TestCase::report() const; 00659 \brief Retorna la hilera encabezado \c summary() seguido \c toString(). 00660 */ 00661 /** \fn const std::string TestCase::failureString() const; 00662 \brief Sinónimo de \c toString(). 00663 */ 00664 /** \fn void TestCase::recordSuccess(); 00665 \brief Registra como exitoso el resultado de una prueba. 00666 */ 00667 /** \fn int TestCase::nPass() const; 00668 \brief Sinónimo de \c successCount() [OBSOLETO]. \deprecated 00669 */ 00670 /** \fn int TestCase::nError() const; 00671 \brief Sinónimo de \c failureCount() [OBSOLETO]. \deprecated 00672 */ 00673 /** \fn virtual bool TestCase::iAmTestSuite() const; 00674 \brief Retorna \c false para \c TestCase. 00675 */ 00676 /** \fn TestCase::TestCase(const TestCase&); 00677 \brief Esta declaración \c "private" prohibe la copia de casos de prueba. 00678 */ 00679 /** \fn TestCase& TestCase::operator=(const TestCase&); 00680 \brief Esta declaración \c "private" prohibe la copia de casos de prueba. 00681 */ 00682 #endif 00683 00684 #ifdef Spanish_dox 00685 /** Constructor. 00686 Si no se indica el nombre en \c "name", después el nombre se obtiene 00687 invocando <code>typeid(*this).name()</code>. 00688 */ 00689 #endif 00690 #ifdef English_dox 00691 /** Constructor. 00692 If no name is given to this constructor in \c "name", later the 00693 name will be obtained invoking <code>typeid(*this).name()</code>. 00694 */ 00695 #endif 00696 /** \dontinclude test_BUnit.cpp 00697 \skipline test::constructor() 00698 \until }} 00699 \see test_BUnit::test_constructor() 00700 */ 00701 inline TestCase::TestCase(const char * name) : 00702 m_pass(0), m_failure(0), m_name(name), 00703 m_test_suite_destroy(false), m_failureList() { } 00704 00705 #ifdef Spanish_dox 00706 /** Elimina todas las pruebas realizadas. 00707 - Anula los contadores de pruebas porque deja la clase en el estado 00708 inicial que tuvo al ser construida. 00709 - Borra el registro de pruebas no exitosas. 00710 - No borra el nombre de la prueba. 00711 */ 00712 #endif 00713 #ifdef English_dox 00714 /** Discards all test runs. 00715 - Resets to cero al counters because the test case is left in 00716 the state it had when initially contructed. 00717 - Deletes the record for not successful tests. 00718 - Does not change the test case name. 00719 */ 00720 #endif 00721 /** \dontinclude test_BUnit.cpp 00722 \skipline test::reset() 00723 \until }} 00724 \see test_BUnit::test_reset() 00725 */ 00726 inline void TestCase::reset() { 00727 m_pass = m_failure = 0; 00728 m_failureList.clear(); 00729 } 00730 00731 inline std::string TestCase::getName() const { 00732 return ( m_name != 0 ? m_name : typeid(*this).name() ); 00733 } 00734 00735 #ifdef Spanish_dox 00736 /** Le cambia el nombre a la prueba por \c "name". 00737 - Si \c "name" es una hilera o puntero nulo, después 00738 usa <code>typeid(*this).name()</code> para obtener 00739 el nombre de la prueba. 00740 */ 00741 #endif 00742 #ifdef English_dox 00743 /** Sets the test case name to \c "name". 00744 - When \c "name" is a null string or pointer, later 00745 <code>typeid(*this).name()</code> will be invoked 00746 to get the test´s name. 00747 */ 00748 #endif 00749 /** \dontinclude test_BUnit.cpp 00750 \skipline test::setName() 00751 \until }} 00752 \see test_BUnit::test_setName() 00753 */ 00754 inline void TestCase::setName( const char * name ) { 00755 m_name = name; 00756 } 00757 00758 #ifdef Spanish_dox 00759 /** Ejecuta la prueba <code>setUp(); run(); tearDown();</code>. 00760 - A diferencia de \c run(), este método sí establece el ambiente 00761 de prueba invocando \c setUp() y \c tearDown() antes y después 00762 de hacer la prueba. 00763 */ 00764 #endif 00765 #ifdef English_dox 00766 /** Excecutes the test run <code>setUp(); run(); tearDown();</code>. 00767 - In contrast to \c run(), this method will setup the environment 00768 for the test run invoking \c setUp() and \c tearDown() before and 00769 after the test. 00770 */ 00771 #endif 00772 /** \dontinclude test_BUnit.cpp 00773 \skipline test::run() 00774 \until }} 00775 \see test_BUnit::test_run() 00776 */ 00777 inline void TestCase::runBare( ) { setUp(); run(); tearDown(); } 00778 00779 #ifdef Spanish_dox 00780 /** Establece el ambiente para la ejecución de la prueba. 00781 Esta clase existe para mejorar la compatibilidad con JUnit. 00782 \see TestCase::setUp() 00783 */ 00784 #endif 00785 #ifdef English_dox 00786 /** Sets the environment for the test run. 00787 This clase exists to improve compatibility with JUnit. 00788 \see TestCase::setUp() 00789 */ 00790 #endif 00791 typedef TestCase TestFixture; 00792 00793 #ifdef Spanish_dox 00794 /** Establece el ambiente en que se realizará la prueba. 00795 - Como \c TestCase::run() es un método abstracto, para facilitar la 00796 programación lo usual es que el programador no incluya invocaciones 00797 a \c TestCase::setUp() y \c TestCase::tearDown() pues es más fácil 00798 dejar que lo haga \c TestSuite<TestCase>::runBare(). 00799 - A diferencia de \c TestCase::runBare(), el método \c TestCase::run() 00800 no establece el ambiente de prueba porque no invoca ni a 00801 \c TestCase::setUp() antes de la prueba ni a \c TestCase::tearDown() 00802 después de la prueba. 00803 - \c TestSuite<TestCase>::runBare() invoca los métodos 00804 \c TestCase::setUp() y \c TestCase::tearDown() cuando ejecuta cada 00805 prueba. 00806 - Si el programador cliente quiere que cada prueba se ejecute luego de 00807 establecer el ambiente de la prueba, lo más práctico es que agregue 00808 sus pruebas a una colección de pruebas \c TestSuite para ejecutarlas 00809 con \c TestSuite<TestCase>::runBare(). 00810 */ 00811 #endif 00812 #ifdef English_dox 00813 /** Sets the environment for the test run. 00814 - As \c TestCase::run() is an abstract method, to facilitate 00815 programming it is usual for the programmer not to invoke 00816 \c TestCase::setUp() and \c TestCase::tearDown() because it is 00817 easier to have \c TestSuite<TestCase>::runBare() do it. 00818 - In contrast with \c TestCase::runBare(), method \c TestCase::run() 00819 will not establish the test environment because it does not 00820 invoke neither \c TestCase::setUp() before the test run nor 00821 \c TestCase::tearDown() after the test run. 00822 - \c TestSuite<TestCase>::runBare() invokes methods 00823 \c TestCase::setUp() and \c TestCase::tearDown() when the test run 00824 is executed. 00825 - If the client programmer wants each test run to stablish it test 00826 environment, it is easier to put all test cases into a test collection 00827 \c TestSuite and execute all of them invoking 00828 \c TestSuite<TestCase>::runBare(). 00829 */ 00830 #endif 00831 inline void TestCase::setUp() { } 00832 00833 #ifdef Spanish_dox 00834 /// Destruye el ambiente de prueba. 00835 #endif 00836 #ifdef English_dox 00837 /// Destroys the test environment. 00838 #endif 00839 inline void TestCase::tearDown() {} 00840 00841 #ifdef Spanish_dox 00842 /** Efectúa la prueba y registra su resultado. 00843 - Si la prueba fue exitosa sólo incrementa la cantidad de éxitos 00844 \c successCount(). 00845 - Si la prueba no tuvo éxito reporta en \c toString() ese hecho. 00846 - El resultado de la prueba es \c "cond". 00847 - Los valores \c "fname" y \c "lineno" indican el archivo y el renglón 00848 en donde se ejecuta la prueba. 00849 - Usualmente los valores de \c "fname" y \c "lineno" se obtienen con 00850 las macros globales \c "__FILE__" y \c "__LINE__". 00851 - El valor \c "must_copy" indica que es necesario hacer una copia de la 00852 hilera \c "label", copia que será destruida cuando el registro de 00853 pruebas no exitosas sea borrado. 00854 - En la mayor parte de los casos, la hilera \c "label" es una constante 00855 generada por el preprocesador al usar la macro \c \#cond y por eso su 00856 memoria no debe ser retornada. 00857 Este método es invocado usando la macro \c BUnit_TEST(). 00858 */ 00859 #endif 00860 #ifdef English_dox 00861 /** Executes the test and records its result. 00862 - If the test is successful only increases the numbero of success 00863 \c successCount(). 00864 - If the test is not successful reports in \c toString() this fact. 00865 - The result of the test is \c "cond". 00866 - Values \c "fname" and \c "lineno" show the file and line of the 00867 executed test. 00868 - Usuallyy \c "fname" and \c "lineno" are values obtained with global 00869 macros \c "__FILE__" and \c "__LINE__". 00870 - The value for \c "must_copy" indicates whether it is necessary to 00871 make a copy of string \c "label"; this copy will be destroyed when 00872 the record of not successful test is deleted. 00873 - Most of the time string \c "label" is a constant genertated by the 00874 preprocessor when using macro \c \#cond its memory must not be 00875 returned. 00876 This method is invoked using macro \c BUnit_TEST(). 00877 */ 00878 #endif 00879 /** \dontinclude test_BUnit.cpp 00880 \skipline test::testThis() 00881 \until }} 00882 \see test_BUnit::test_testThis() 00883 */ 00884 inline void TestCase::testThis( 00885 bool cond, const char * label, const char* fname, long lineno, bool must_copy ) 00886 { 00887 if (cond) { 00888 recordSuccess(); 00889 } 00890 else { 00891 recordFailure( label, fname, lineno, must_copy ); 00892 } 00893 } 00894 00895 #ifdef Spanish_dox 00896 /// Sinónimo de \c testThis(). 00897 #endif 00898 #ifdef English_dox 00899 /// Synonym for \c testThis(). 00900 #endif 00901 inline void TestCase::testThis( 00902 bool cond, const std::string& label, const char* fname, long lineno ) 00903 { 00904 testThis( cond, label.c_str(), fname, lineno, true /* must_copy == true */ ); 00905 /* NOTE: In the class instance the name for the test case is stored as 00906 a (char*). If a std::string is used for "label", it must be converted to 00907 a (char*) that will have to be destroyed when the test instance gets 00908 destroyed. This is why parameter "must_copy" must be set to "true". 00909 */ 00910 } 00911 00912 #ifdef Spanish_dox 00913 /** Registra que la prueba no tuvo éxito. 00914 - Los valores \c "fname" y \c "lineno" indican el archivo y el renglón 00915 en donde se ejecuta la prueba. 00916 - Usualmente los valores de \c "fname" y \c "lineno" se obtienen invocando 00917 las macros globales \c "__FILE__" y \c "__LINE__". 00918 - El valor \c "must_copy" indica que es necesario hacer una copia de la 00919 hilera \c "label" en memoria dinámica. Este memoria dinámica será destruida 00920 cuando el caso de prueba sea destruido o cuando el método \c TestCase::reset() 00921 sea invocado. 00922 - En la mayor parte de los casos, la hilera \c "label" es una constante 00923 generada por el preprocesador al usar la macro \c \#cond; como esta hilera 00924 constante no está almacenada en la memoria dinámica no debe ser destruida. 00925 00926 Este método es invocado usando la macro \c BUnit_FAILURE(). 00927 */ 00928 #endif 00929 #ifdef English_dox 00930 /** Records that the test run did not succeed. 00931 - Values \c "fname" and \c "lineno" indicate the file and line where 00932 the test run is executed. 00933 - The values form \c "fname" and \c "lineno" are usuallly obtained 00934 invoking global macros \c "__FILE__" and \c "__LINE__". 00935 - \c "must_copy" forces a copy of string label to be created in dynamic 00936 memory. This dynamic memory will be destroyed when the test case gets 00937 destroyed or when method \c TestCase::reset() gets invoked. 00938 - Oftentimes string \c "label" is a constant string generated by the 00939 preprocessor macro using \c \#cond; this string constant is not stored 00940 in dynamic memory and it must not be destroyed. 00941 00942 This method is invoked using macro \c BUnit_FAILURE(). 00943 */ 00944 #endif 00945 inline void TestCase::recordFailure( 00946 const char* label, const char* fname, int lineno, bool must_copy ) 00947 { 00948 if ( must_copy ) { 00949 size_t len = strlen(label)+1; 00950 char* str = new char[ len ]; // copies the failure message 00951 memcpy( str, label, len ); 00952 label = str; 00953 } 00954 m_failureList.push_back( TestCaseFailure ( fname, lineno, label, must_copy ) ); 00955 m_failure++; 00956 /* NOTE: When this method is invoked directly it is because "label" is a 00957 constant (char*) string, produced by one of the BUnit_TEST() macro using 00958 operator "#" (as in #cond). As this is a constant string, it it not 00959 necessary to return its memory when the instance of "TestCase" gets 00960 destroyed and, as result of this, field "m_destroy_label" in the 00961 corresponding "TestCaseFailure" instance must be false. 00962 00963 In contrast, when "label" is generated from std::string, the method 00964 recordFailure() to be invoked is not this. Intead the method invoked will be 00965 the other version of recordFailure() where parameter "label" is a std::string. 00966 That other version always uses "true" for "must_copy", because a (char*) copy 00967 of the original std::string is stored in the "TestCaseFailure" instance, and 00968 that value should be destroyed when that instance gets destroyed. This fact 00969 gets recorded in field "TestCaseFailure::m_destroy_label." 00970 00971 This means that no extra work is necessary to handle the two different cases 00972 (char*) vs std::string, as the compiler chooses correctly which version of 00973 recordFailure() to use. 00974 */ 00975 /* NOTA: Cuando este método es invocado directamente es porque "label" es una 00976 hilera constante (char*), producida por alguna de las macro BUnit_TEST() 00977 mediante el operador "#" (como en #cond). Como esa hilera es constante, no 00978 hace falta retornar su memoria cuando la instancia de "TestCase" sea destruida 00979 y, en consecuencia, el campo "m_destroy_label" de la instancia de 00980 "TestCaseFailure" correspondiente debe ser "false". 00981 00982 En contraposición, si la hilera "label" es generada a partir de std::string, el 00983 método recordFailure() que será invocado no es éste. Más bien será la otra 00984 versión de recordFailure() la invocada, pues en esa "label" es de tipo 00985 std::string. Esa otra versión siempre usa "true" para "must_copy", pues una 00986 copia (char*) del valor original std::string queda almacenada en la instancia 00987 "TestCaseFailure" y ese valor debe ser destruido cuando esa instancia sea 00988 destruida. Este hecho quda registrado en el campo "TestCaseFailure::m_destroy_label." 00989 00990 Esto quiere decir que no hace falta hacer trabajo adicional para manejar los 00991 dos casos diferentes "char*" vs "std::string", pues el compilador escoge 00992 correctamente siempre cuál versión de recordFailure() que hay que usar. 00993 */ 00994 } 00995 00996 #ifdef Spanish_dox 00997 /// Registra que la prueba no tuvo éxito. 00998 /// - En \c BUnit.h no se hace diferencia entre "fallas" y "errores". 00999 #endif 01000 #ifdef English_dox 01001 /// Records that the test did not succeed. 01002 /// - En \c BUnit.h there is no difference between "failures" and "errors". 01003 #endif 01004 inline void TestCase::recordFailure( 01005 const std::string& label, const char* fname, int lineno ) 01006 { 01007 recordFailure( label.c_str(), fname, lineno, true /* must_copy == true */ ); 01008 /* NOTE: as in here the (char*) version of recordFailure() is invoked for it to 01009 make a copy of "label.c_str()", argument "must_copy" must be set to "true". 01010 In this way field "TestCaseFailure::m_destroy_label" will be se to "true", 01011 and the (char*) memory for the copy of string "label.c_str()" will be 01012 returned when the record for the "TestCaseFailure" is destroyed. 01013 */ 01014 /* NOTA: como aquí se invoca a la versión (char*) de recordFailure() para que 01015 haga una copia de "label.c_str()", el argumento "must_copy" debe ser "true". 01016 De esta manera el campo "TestCaseFailure::m_destroy_label" tomará el valor 01017 "true" y, en consecuencia, la memoria (char*) en donde quedó la copia de la 01018 hilera "label.c_str()" será retornada cuando el registro de la prueba 01019 "TestCaseFailure" sea destruido. 01020 */ 01021 } 01022 01023 #ifdef Spanish_dox 01024 /// Hilera "enooorme" que contiene copia del registro de pruebas no exitosas, separados por \c "\n". 01025 #endif 01026 /// Huuuge string that holds a copy of non successfull test, separated by \c "\n". 01027 #ifdef English_dox 01028 #endif 01029 /** \code 01030 =\_fail: 1 == 0 01031 =/ (125) X:/DIR/SubDir/test_BUnit.cpp 01032 =\_fail: 4 == 0 01033 =/ (128) X:/DIR/SubDir/test_BUnit.cpp 01034 \endcode 01035 */ 01036 inline const std::string TestCase::toString() const { 01037 // typedef basic_ostringstream<char> ostringstream; 01038 std::basic_ostringstream<char> ost; // ostringstream ost; 01039 do_toString( this , ost ); 01040 return ost.str(); 01041 } 01042 01043 #ifdef Spanish_dox 01044 /// Le agrega a \c ost la hilera de todas las pruebas no exitosas de \c *tc. 01045 #endif 01046 #ifdef English_dox 01047 /// Adds to \c ost the string of al unsuccessful test from \c *tc. 01048 #endif 01049 template <class TestCase> 01050 void do_toString( const TestCase * tc , std::basic_ostringstream<char> & ost ) { 01051 std::list<TestCaseFailure>::const_iterator it = tc->m_failureList.begin(); 01052 for ( ; it != tc->m_failureList.end(); ++it) { 01053 ost << "=\\_fail: " << it->m_label << " \n=/ (" 01054 << it->m_lineno << ") " << it->m_fname << "\n"; 01055 } 01056 return; 01057 /* NOTA: La implementación de "TestCase::toString()" está hecha invocando esta 01058 función emplantillada para que sea el compilador el responsable de remover 01059 versiones duplicadas de esta misma rutina, las que se producen cuando este 01060 archivo de encabezado ("BUnit.h") es incluido en varios archivos "*.cpp". 01061 Todo esto hay que hacerlo para que "BUnit.h" quepa, completo, en un único 01062 archivo de encabezado. 01063 */ 01064 /* NOTE: the implementation for "TestCase:toString()" is made invoking this 01065 template function for the compiler to be responsible of removing duplicate 01066 versions of this same routine, which would be produced when this header file 01067 ("BUnit.h") gets included in several "*.cpp" files. All this must be done 01068 for "BUnit.h" to fit, completely, in a single header file. 01069 */ 01070 } 01071 01072 #ifdef Spanish_dox 01073 /// Hilera XML que contiene una copia de las pruebas no exitosas. 01074 #endif 01075 #ifdef English_dox 01076 /// XML string that holds a copy of all unsuccessful tests. 01077 #endif 01078 /** \code 01079 <fail file="X:/DIR/SubDir/test_BUnit.cpp" line="125" message="1 == 0"/> 01080 <fail file="X:/DIR/SubDir/test_BUnit.cpp" line="128" message="4 == 0"/> 01081 \endcode 01082 */ 01083 inline const std::string TestCase::toXML() const { 01084 // typedef basic_ostringstream<char> ostringstream; 01085 std::basic_ostringstream<char> ost; // ostringstream ost; 01086 do_toXML( this , ost ); 01087 return ost.str(); 01088 } 01089 01090 #ifdef Spanish_dox 01091 /// Le agrega a \c ost la hilera de todas las pruebas no exitosas de \c *tc en formato XML. 01092 #endif 01093 #ifdef English_dox 01094 /// Adds to \c ost the string of al unsuccessful test from \c *tc in XML format 01095 #endif 01096 template <class TestCase> 01097 void do_toXML( const TestCase * tc , std::basic_ostringstream<char> & ost ) { 01098 std::list<TestCaseFailure>::const_iterator it = tc->m_failureList.begin(); 01099 for ( ; it != tc->m_failureList.end(); ++it ) { 01100 ost << "<fail file=\"" << it->m_fname 01101 << "\" line=\"" << it->m_lineno 01102 << "\" message=\"" << it->m_label << "\"/>" << std::endl; 01103 } 01104 return; 01105 /* NOTE: the implementation for "TestCase:toXML()" is made invoking this 01106 template function for the compiler to be responsible of removing duplicate 01107 versions of this same routine, which would be produced when this header file 01108 ("BUnit.h") gets included in several "*.cpp" files. 01109 */ 01110 /* NOTA: La implementación de "TestCase::toXML()" está hecha invocando a la 01111 función emplantillada para que sea el compilador el responsable de remover 01112 versiones duplicadas de esta misma rutina, las que se producen cuando este 01113 archivo de encabezado ("BUnit.h") es incluido en varios archivos "*.cpp". 01114 */ 01115 } 01116 01117 /// [BUnit] ==> BUnit.h 01118 #define TEST_BUnit() 01119 #undef TEST_BUnit 01120 01121 #ifdef Spanish_dox 01122 /** [BUnit] Efectúa la prueba \c "cond y registra el resultado. 01123 - Es más elegante usar \c assertTrue() que hace lo mismo. 01124 - Si la prueba \c "cond" tiene éxito invoca el método 01125 \c TestCase::recordSuccess(). 01126 - Si la prueba \c "cond" no tiene éxito invoca el método 01127 \c TestCase::recordFailure(). 01128 */ 01129 #endif 01130 #ifdef English_dox 01131 /** [BUnit] Executes test \c "cond and records its result. 01132 - It is more elegant to use \c assertTrue() for the same purpose. 01133 - If test \c "cond" is successful method \c TestCase::recordSuccess() 01134 is invoked. 01135 - If test \c "cond" is not successful, method\c TestCase::recordFailure() 01136 is invoked. 01137 */ 01138 #endif 01139 /** \dontinclude test_BUnit.cpp 01140 \skipline test::BUnit_macro() 01141 \until }} 01142 \see test_BUnit::test_BUnit_macro() 01143 */ 01144 #define BUnit_TEST(cond) testThis( cond, #cond, __FILE__, __LINE__ ) 01145 01146 #ifdef Spanish_dox 01147 /// [BUnit] Macro similar a \c BUnit_TEST() que usa el mensaje \c "msg". 01148 /// - El mensaje \c "msg" debe ser una hilera (char*) literal o un objeto 01149 /// que pueda convertirse en <code>(const char *)</code>. 01150 #endif 01151 #ifdef English_dox 01152 /// [BUnit] Macro similar to \c BUnit_TEST() that uses mesaje \c "msg". 01153 /// - Mensaje \c "msg" must be a literal (char*) string or and object that 01154 /// can be converted into a <code>(const char *)</code>. 01155 #endif 01156 #define BUnit_TEST_Msg(msg, cond) testThis( cond, msg, __FILE__, __LINE__ ) 01157 01158 #ifdef Spanish_dox 01159 /** [BUnit] Registra como "falla" el resultado de una prueba. 01160 - El programador cliente es quien determinó que la prueba no tuvo éxito 01161 y quiere registrar ese hecho. 01162 - Está implementado comun una macro que sirve de empaque para invocar 01163 el método \c TestCase::recordFailure(). 01164 */ 01165 #endif 01166 #ifdef English_dox 01167 /** [BUnit] Records as "failure" the result of a test. 01168 - The client programmer determined that the test did not succeed 01169 and wants to record this fact. 01170 - It is implemented as a macro wrapper to invoke method 01171 \c TestCase::recordFailure(). 01172 */ 01173 #endif 01174 /** \see BUnit_TEST() 01175 \code 01176 if (22==33) { 01177 BUnit_FAILURE("! (22==33)"); // records failure 01178 } 01179 \endcode 01180 */ 01181 #define BUnit_FAILURE(msg) recordFailure( msg, __FILE__, __LINE__ ) 01182 01183 #ifdef Spanish_dox 01184 /** [BUnit] Registra como "exitoso" el resultado de una prueba. 01185 - El programador cliente es quien determinó que la prueba 01186 fue exitosa y quiere registrar ese hecho. 01187 - Generalmente se usa después de atrapar una excepción que 01188 se supone debió ser lanzada como resultado de la prueba. 01189 - Está implementado como una macro que invoca el método 01190 \c TestCase::recordSuccess(). 01191 \see BUnit_TEST() 01192 */ 01193 #endif 01194 #ifdef English_dox 01195 /** [BUnit] Records as "successful" the result of a test. 01196 - The client programmer determined that the test did succeed 01197 and wants to record this fact. 01198 - Usually used after catching an exception that should have 01199 been raised as result of the test. 01200 - It is implemented as a macro wrapper to invoke method 01201 \c TestCase::recordSuccess(). 01202 \see BUnit_TEST() 01203 */ 01204 #endif 01205 #define BUnit_SUCCESS() recordSuccess() 01206 01207 #ifdef Spanish_dox 01208 /// [BUnit] Efectúa la prueba para determinar si <code>(expected == actual)</code>. 01209 /// - Si la prueba tiene éxito invoca el método \c TestCase::recordSuccess(). 01210 /// - De otra manera invoa \c TestCase::recordFailure(). 01211 /// - Esta es una una macro que invoca el método \c TestCase::testThis(). 01212 /// \see BUnit_TEST() 01213 #endif 01214 #ifdef English_dox 01215 /// [BUnit] Executes the test to determine if <code>(expected == actual)</code>. 01216 /// - On success invokes method \c TestCase::recordSuccess(). 01217 /// - Otherwise invokes \c TestCase::recordFailure(). 01218 /// - This is a macro to invoke method \c TestCase::testThis(). 01219 /// \see BUnit_TEST() 01220 #endif 01221 #define BUnit_EQUAL(expected, actual) \ 01222 testThis( (expected) == (actual), #expected " == " #actual, __FILE__, __LINE__ ) 01223 01224 #ifdef Spanish_dox 01225 /// [BUnit] Efectúa la prueba para determinar si <code>expected == actual</code>. 01226 /// - Si la prueba tiene éxito invoca el método 01227 /// \c TestCase::recordSuccess(). 01228 /// - Si la prueba no tiene éxito invoca el método 01229 /// \c TestCase::recordFailure(). 01230 /// - Esta es una una macro que invoca el método 01231 /// \c TestCase::testThis(). 01232 /// - Registra el mensaje \c "MSG" si la prueba no tiene éxito. 01233 /// \see BUnit_TEST() 01234 #endif 01235 #ifdef English_dox 01236 /// [BUnit] Executes the test to determine if <code>(expected == actual)</code>. 01237 /// - On success invokes method \c TestCase::recordSuccess(). 01238 /// - Otherwise invokes \c TestCase::recordFailure(). 01239 /// - This is a macro to invoke method \c TestCase::testThis(). 01240 /// - Records messaje \c "MSG" if the test is not successful. 01241 /// \see BUnit_TEST() 01242 #endif 01243 #define BUnit_EQUAL_Msg(MSG, expected, actual) \ 01244 testThis( (expected) == (actual), MSG, __FILE__, __LINE__ ) 01245 01246 #ifdef Spanish_dox 01247 /// Retorna un hilera que contiene el nombre, cantidad de éxitos y fallas. 01248 #endif 01249 #ifdef English_dox 01250 /// Returns a string with the name, number of successes and failures. 01251 #endif 01252 inline const std::string TestCase::summary() const { 01253 std::string res = "TestCase [" + getName() + ']'; 01254 res += " (OK: " + TestCase::toString( successCount() ) + ')'; 01255 res += " (FAIL: " + TestCase::toString( failureCount() ) + ')'; 01256 return res; 01257 } 01258 01259 /************************\ 01260 ************************** 01261 ** ** 01262 ** TestSuite ** 01263 ** ** 01264 ************************** 01265 \************************/ 01266 // template <class TestCase> class TestSuite 01267 #ifdef Spanish_dox 01268 /** \class TestSuite 01269 \brief Colección de pruebas. 01270 - Este un contenedor simple con una interfaz similar a la de la clase 01271 \c TestCase. 01272 - Cada una de las pruebas de la colección es ejecutada mediante la 01273 invocación a su método \c TestCase::run(). 01274 - El método \c TestSuite<TestCase>::runBare() es similar a 01275 \c TestSuite<TestCase>::run(), pero antes de hacer cada prueba establece 01276 el ambientede ejecución de la prueba invocando a \c TestCase::setUp() 01277 y a \c TestCase::tearDown() después de realizarla. 01278 - Debido al uso de los métodos \c setUp() y \c tearDown() para ejecutar 01279 las pruebas de la colección, cada prueba queda "aisalda" de las demás, 01280 pues para cada una se estable el ambiente de ejecución que promete la 01281 clase \c TestCase. 01282 - Está implementado como una plantilla para evitar usar un archivo 01283 \c "BUnit.cpp", de manera que para probar programas baste incluir 01284 únicamente este archivo \c "BUnit.h". 01285 01286 \par Truco para evitar usar el archivo \c "BUnit.cpp" 01287 01288 - Al implementar la plantilla \c TestSuite<> usé como parámetro el identificador 01289 \c TestCase, que también es el nombre de la clase de la que \c TestSuite<> se 01290 deriva. Este doble uso del mismo identificador confunde al compilador, porque 01291 no puede deducir que el parámetro \c TestCase también es el nombre de la clase 01292 base. Por eso, uso un sinónimo para nombrar a la clase base de \c TestSuite<>. 01293 Escogí el identificador \c TestCase_is_base_for_TestSuite porque es 01294 descriptivo y bastante largo, por lo que es muy poco probable que un 01295 programador cliente de \c BUnit.h necesite usarlo. 01296 - La clase \c TestSuite<> está implementada usando plantillas para evitar 01297 forzar al programador cliente de \c "BUnit" a usar 2 archivos, uno de 01298 encabezado \c "BUnit.h" y otro de implementación \c "BUnit.cpp". Como no 01299 hace falta usar el archivo \c "BUnit.cpp", implementar programas de 01300 prueba es muy sencillo pues al programar las pruebas solo se necesita 01301 agregar este único renglón: 01302 - <code>\#include "BUnit.h"</code> 01303 - Si toda la implementación de \c "BUnit" está contenida en el archivo de 01304 encabezado de \c "BUnit.h", puede ocurrir que algunas rutinas queden 01305 duplicadas en el programa objeto cuando el encabezado \c "BUnit.h" es 01306 incluido en varios archivos \c ".cpp" diferentes en el mismo proyecto. 01307 En estos casos, los métodos que no son <em>"inline"</em> quedan 01308 definidos en varios archivos y, en consecuencia, el editor de 01309 eslabonamiento (<em>"linker"</em>) debe reportar que el mismo módulo 01310 objeto está presente en varios archivos objeto. Cuando se usan 01311 plantillas, el sistema de compilacición se encarga de manejar esta 01312 duplicación, lo que releva al programador de esta engorrosa 01313 responsabilidad. Esto explica por qué \c TestSuite<> es una clase 01314 emplantillada. 01315 - La otra forma de lograr evitar la duplicación de módulos objetos es 01316 obligar a los programadores cliente a incluir en su proyecto el archivo 01317 \c "BUnit.cpp" en donde estarían las definiciones de las funciones que 01318 no son <em>"inline"</em>. 01319 01320 - En otras palabras, el requerimiento de lograr que todas la 01321 implementación de \c BUnit.h esté metida en un sólo archivo obliga a 01322 implementar \c TestSuite<> con plantillas, lo que a también motiva el 01323 uso de \c TestCase como nombre del parámetro para la plantilla 01324 \c TestSuite<>. 01325 - Dicho de otra manera: la razón por la que \c TestSuite<> está 01326 implementada con plantillas es lograr que la responsabilidad de eliminar 01327 duplicados de métodos y funciones caiga en el sistema de compilación, 01328 pues de lo contrario sería necesario que los programadores cliente incluyan 01329 en su proyecto el archivo de implementación \c "BUnit.cpp", lo que haría 01330 más complicado el uso de \c BUnit. Este truco de programación hace que 01331 sea trabajo del compilador manejar el código de implementación que de 01332 otra manera habria habido que poner dentro de un archivo de 01333 implementación \c "BUnit.cpp". 01334 */ 01335 #endif 01336 #ifdef English_dox 01337 /** \class TestSuite; 01338 \brief Test collection. 01339 - This is a container with an interface similar to class \c TestCase. 01340 - Each test case in the collection is executed invoking its \c TestCase::run() 01341 method. 01342 - Method \c TestSuite<TestCase>::runBare() is similar to 01343 \c TestSuite<TestCase>::run(), but before each test the test environment 01344 for the test is established invoking \c TestCase::setUp() and 01345 \c TestCase::tearDown() afterwards. 01346 - Because of the use of methods \c setUp() and \c tearDown() to exectute test 01347 in the collection, each tests becomes "isolated" from the rest, because 01348 each stablishes its execution environment promised by class \c TestCase. 01349 - This implementation uses templates to avoid using a file \c "BUnit.cpp", 01350 to allow program testis using a single include of file \c "BUnit.h". 01351 01352 \par Trick to avoid using file \c "BUnit.cpp" 01353 01354 - When implementing the \c TestSuite<> template I used as parameter identifier 01355 \c TestCase, which is also the name for the class from where \c TestSuite<> 01356 is derived. This dual use of the same identifier confuses the compiler, 01357 because it can not figure out that parameter \c TestCase is also the name 01358 for the base class. Therefore, I use a synonym to name the base class for 01359 \c TestSuite<>. I chose identifier \c TestCase_is_base_for_TestSuite 01360 because it is descriptive and quite long, so it is very unlikely that client 01361 programmer of \c BUnit.h would ever need to use it. 01362 - Class \c TestSuite<> is implemented using templates to avoid forcing the 01363 client programmer of \c "BUnit" to use 2 files, a header file 01364 \c "BUnit.h" and another to hold the implementation \c "BUnit.cpp." As 01365 there is no need to use the file \c "BUnit.cpp", implementing test 01366 programs is easy because programming test cases only requires adding 01367 this single line: 01368 - <code>\#include "BUnit.h"</code> 01369 - If the entire implementation of \c "BUnit" is contained in header file 01370 \c "BUnit.h", it may happen that some routines get duplicated in the 01371 object code when header file \c "BUnit.h" is included from several 01372 different \c ".cpp" files in the same project. In these cases, methods 01373 that are not <em>"inline"</em> are defined in several files and, 01374 consequently, the linkage editor (<em>"linker"</em>) should report that 01375 the same object module is present in several object files. When 01376 templates are used, the compiling system is responsible for managing 01377 this duplicating what relieves the programmer of this cumbersome 01378 responsibility. This explains why \c TestSuite<> is a template class. 01379 - Another way to avoid duplication of object modules it to force the 01380 client programmers to include in their project file \c "BUnit.cpp" 01381 containing all definition for non <em>"inline"</em> functions. 01382 01383 - In other words, the requirement to make all the implementatation of 01384 \c BUnit.h to fit into a single file forces implementing 01385 \c TestSuite<> with templates, which also motivates the use 01386 \c TestCase as the name name of the parameter template 01387 \c TestSuite<>. 01388 - Put in another way: the reason why \c TestSuite<> is implemented with 01389 templates is to ensure that the responsibility for removing duplicate 01390 functions and methods belongs to the compiling system, as otherwise the 01391 client programmers would be required to include in their proyect 01392 implementation file \c "BUnit.cpp", which would make more complicated 01393 using \c BUnit. This programming trick puts the compiler in charge of 01394 handling the implementation coide that otherwise would have been put in 01395 an implementation file\c "BUnit.cpp." 01396 */ 01397 #endif 01398 01399 #ifdef Spanish_dox 01400 /** \fn template <class TestCase> typedef TestSuite<TestCase>::container_type; 01401 \brief Tipo del contenedor (escoja el que prefiera). 01402 */ 01403 /** \fn template <class TestCase> typedef TestSuite<TestCase>::iterator; 01404 \brief Iterador del contenedor. 01405 */ 01406 /** \fn template <class TestCase> typedef TestSuite<TestCase>::cons_iterator; 01407 \brief Iterador del contenedor (\c const). 01408 */ 01409 /** \fn template <class TestCase> typedef TestSuite<TestCase>::const_container_type; 01410 \brief Tipo del contenedor (\c const). 01411 */ 01412 /** \fn template <class TestCase> container_type TestSuite<TestCase>::m_allTest; 01413 \brief Contenedor en donde se almacenan los punteros a las pruebas. 01414 */ 01415 #endif 01416 #ifdef English_dox 01417 /** \fn template <class TestCase> typedef TestSuite<TestCase>::container_type; 01418 \brief Container type (choice your preferred). 01419 */ 01420 /** \fn template <class TestCase> typedef TestSuite<TestCase>::iterator; 01421 \brief Container iterador. 01422 */ 01423 /** \fn template <class TestCase> typedef TestSuite<TestCase>::cons_iterator; 01424 \brief Container iterador (\c const). 01425 */ 01426 /** \fn template <class TestCase> typedef TestSuite<TestCase>::const_container_type; 01427 \brief Container type (\c const). 01428 */ 01429 /** \fn template <class TestCase> container_type TestSuite<TestCase>::m_allTest; 01430 \brief Container to store pointers to tests. 01431 */ 01432 #endif 01433 01434 /** \fn template <class TestCase> TestSuite<TestCase>::TestSuite(const char * name=0); 01435 \brief Constructor 01436 */ 01437 01438 #ifdef Spanish_dox 01439 /** \fn template <class TestCase> TestSuite<TestCase>::TestSuite(const char * name=0); 01440 \brief Constructor. 01441 */ 01442 /** \fn template <class TestCase> int TestSuite<TestCase>::countTestCases() const; 01443 \brief Cantidad de casos de prueba. 01444 */ 01445 /** \fn template <class TestCase> int TestSuite<TestCase>::failureCount() const; 01446 \brief Cantidad de pruebas que fallaron. \see reset(). 01447 */ 01448 /** \fn template <class TestCase> int TestSuite<TestCase>::successCount() const; 01449 \brief Cantidad de pruebas exitosas. \see reset(). 01450 */ 01451 /** \fn template <class TestCase> void TestSuite<TestCase>::reset(); 01452 \brief Elimina todas las pruebas realizadas. 01453 */ 01454 /** \fn template <class TestCase> TestSuite<TestCase>::const_container_type& TestSuite<TestCase>::allTests() const; 01455 \brief Referencia al contenedor con todos los casos de prueba. 01456 */ 01457 /** \fn template <class TestCase> const std::string TestSuite<TestCase>::toString() const; 01458 \brief Hilera "enooorme" que contiene copia del registro de pruebas no exitosas, separados por \c "\n". 01459 */ 01460 /** \fn template <class TestCase> const std::string TestSuite<TestCase>::toXML() const; 01461 \brief Hilera XML que contiene una copia de las pruebas no exitosas. 01462 */ 01463 /** \fn template <class TestCase> bool TestSuite<TestCase>::iAmTestSuite() const { return true; } 01464 \brief Retorna \c true solo para la clase derivada \c TestSuite<>. 01465 */ 01466 /** \fn template <class TestCase> TestSuite<TestCase>::TestSuite(const TestSuite& DONTcopy); 01467 \brief Esta declaración \c "private" prohibe la copia de casos de prueba. 01468 */ 01469 /** \fn template <class TestCase> TestSuite<TestCase>::TestSuite& TestSuite<TestCase>::operator=(const TestSuite& DONTcopy); 01470 \brief Esta declaración \c "private" prohibe la copia de casos de prueba. 01471 */ 01472 #endif 01473 #ifdef English_dox 01474 /** \fn template <class TestCase> TestSuite<TestCase>::TestSuite(const char * name=0); 01475 \brief Constructor. 01476 */ 01477 /** \fn template <class TestCase> int TestSuite<TestCase>::countTestCases() const; 01478 \brief Number of test cases. 01479 */ 01480 /** \fn template <class TestCase> int TestSuite<TestCase>::failureCount() const; 01481 \brief Number of test runs that failed. \see reset(). 01482 */ 01483 /** \fn template <class TestCase> int TestSuite<TestCase>::successCount() const; 01484 \brief Number of successful test runs. \see reset(). 01485 */ 01486 /** \fn template <class TestCase> void TestSuite<TestCase>::reset(); 01487 \brief Discards all test runs. 01488 */ 01489 /** \fn template <class TestCase> TestSuite<TestCase>::const_container_type& TestSuite<TestCase>::allTests() const; 01490 \brief Reference to the container where al the test runs are stored. 01491 */ 01492 /** \fn template <class TestCase> const std::string TestSuite<TestCase>::toString() const; 01493 \brief Huuuge string that holds a copy of non successfull test, separated by \c "\n". 01494 */ 01495 /** \fn template <class TestCase> const std::string TestSuite<TestCase>::toXML() const; 01496 \brief XML string that holds a copy of all unsuccessful tests. 01497 */ 01498 /** \fn template <class TestCase> bool TestSuite<TestCase>::iAmTestSuite() const { return true; } 01499 \brief Returns \c true only for derived class \c TestSuite<>. 01500 */ 01501 /** \fn template <class TestCase> TestSuite<TestCase>::TestSuite(const TestSuite& DONTcopy); 01502 \brief This \c "private" declaration forbids test case copying. 01503 */ 01504 /** \fn template <class TestCase> TestSuite<TestCase>::TestSuite& TestSuite<TestCase>::operator=(const TestSuite& DONTcopy); 01505 \brief This \c "private" declaration forbids test case copying. 01506 */ 01507 #endif 01508 01509 #if 0 01510 #ifdef Spanish_dox 01511 /// Acumula los resultados de pruebas que no tienen éxito. 01512 #endif 01513 #ifdef English_dox 01514 /// Holds results for non successful tests. 01515 #endif 01516 class TestResult { }; // not declared 01517 /* NOTE 01518 As the class TestSuite<> is derived from TestCase, it also 01519 contains a list of tests that have not been successful. That list 01520 is always empty, because the failure logging is carried out 01521 individually, in each instance of TestCase stored in the 01522 TestSuite<> instance. Should BUnit had a TestResult class it would 01523 not be necessary to keep this empty lista. 01524 - To simplify BUunit it contains no TestResult class. 01525 */ 01526 /* NOTA 01527 Como la clase TestSuite<> está derivada de TestCase, también 01528 contiene una lista de pruebas que no han tenido éxito. Esa lista 01529 siempre está vacía, pues el registro de fallas se lleva 01530 individualmente, en cada una de las instancias de TestCase 01531 almacenadas en la instancia de TestSuite. Si BUnit tuviera una 01532 clase TestResult no sería necesario mantener esta lista vacía. 01533 - Para simplificar BUnit no contiene la clase TestResult. 01534 */ 01535 #endif 01536 01537 #ifdef Spanish_dox 01538 /** Agrega la prueba \c "*pT" a la colección \c "*this" (y luego la destruirá). 01539 - Si <code>(pT == 0)</code> no agrega nada y retorna \c "false". 01540 - Es incorrecto que la misma prueba esté más de una vez en la colección. 01541 - Destruirá \c "*pT" cuando \c "*this" sea destruido. 01542 - El parámetro \c "pT" es un puntero. 01543 - Si \c "pT" es una colección de pruebas el efecto es similar a invocar 01544 \c addSuite(*pT) directamente. 01545 */ 01546 #endif 01547 #ifdef English_dox 01548 /** Adds test \c "*pT" to collection \c "*this" (and later it will be destroyed). 01549 - If <code>(pT == 0)</code> nothing is added and returns \c "false". 01550 - It is incorrect for the same test to be in more than one collection. 01551 - Will destroy \c "*pT" when \c "*this" is destroyed. 01552 - The \c "pT" parameter is a pointer. 01553 - If \c "pT" is a test colection the effect is similar to invoking 01554 \c addSuite(*pT) directly. 01555 */ 01556 #endif 01557 /** \dontinclude test_BUnit.cpp 01558 \skipline test::addTest() 01559 \until }} 01560 \see test_BUnit::test_addTest() 01561 */ 01562 template <class TestCase> 01563 bool TestSuite<TestCase>::addTest(TestCase* pT) { 01564 if (pT == 0) { 01565 return false; 01566 } 01567 if ( pT->iAmTestSuite() ) { // ==> addSuite() 01568 addSuite( *( reinterpret_cast< TestSuite<TestCase>* > ( pT ) ) ); 01569 return true; 01570 } 01571 else if ( m_allTest.end() != std::find(m_allTest.begin(), m_allTest.end(), pT) ) { 01572 return false; // never trust the client programmer 01573 } 01574 else { 01575 m_allTest.push_back( pT ); 01576 pT->m_test_suite_destroy = true; 01577 return true; 01578 } 01579 } 01580 01581 #ifdef Spanish_dox 01582 /** Agrega la prueba \c "T" a la colección \c "*this" (no la destruirá). 01583 - No destruirá \c "T" cuando \c "*this" sea destruido. 01584 - El parámetro \c "T" es una referencia. 01585 - Si \c "T" es una colección de pruebas el efecto es similar a invocar 01586 \c addSuite(T) directamente. 01587 */ 01588 #endif 01589 #ifdef English_dox 01590 /** Adds test \c "T" to collection \c "*this" (and later it will not be destroyed). 01591 - Will not destroy \c "T" when \c "*this" is destroyed. 01592 - The \c "T" parameter is a reference. 01593 - If \c "pT" is a test colection the effect is similar to invoking 01594 \c addSuite(T) directly. 01595 */ 01596 #endif 01597 /** \dontinclude test_BUnit.cpp 01598 \skipline test::addTest() 01599 \until }} 01600 \see test_BUnit::test_addTest() 01601 */ 01602 template <class TestCase> 01603 bool TestSuite<TestCase>::addTest(TestCase& T) { 01604 if ( T.iAmTestSuite() ) { // ==> addSuite() 01605 addSuite( *( reinterpret_cast< TestSuite<TestCase>* > ( & T ) ) ); 01606 return true; 01607 } 01608 else if ( addTest(& T) ) { 01609 T.m_test_suite_destroy = false; 01610 return true; 01611 } 01612 else { 01613 return false; 01614 } 01615 } 01616 01617 #ifdef Spanish_dox 01618 /** Traslada todas las pruebas de la colección \c "SSS" y las agrega a \c "*this". 01619 - Deja a \c "SSS" vacía. 01620 - No copia las pruebas de \c SSS para evitar los problemas que surgen cuando 01621 tanto \c "SSS" como \c "*this" tratan de destruir la misma prueba. 01622 - No es posible hacer una jerarquía de pruebas pues todas quedan aplanadas 01623 en un sola colección. 01624 */ 01625 #endif 01626 #ifdef English_dox 01627 /** Moves all test from collection \c "SSS" and ads them to \c "*this". 01628 - Leaves \c "SSS" empty. 01629 - Will not copy tests form \c SSS to avoid problems that come up when 01630 both \c "SSS" and \c "*this" try to destroy the same test. 01631 - It is not possible to make a test hierarchy because all become 01632 flattened in a single collection. 01633 */ 01634 #endif 01635 01636 template <class TestCase> 01637 inline void TestSuite<TestCase>::addSuite( TestSuite& SSS ) { 01638 if (&SSS == 0) { // SSS = (TestSuite<TestCase>*)(0); 01639 return; 01640 } 01641 if ( this == &SSS ) { 01642 return; // avoid self-copy 01643 } 01644 while ( ! SSS.m_allTest.empty() ) { 01645 iterator it = SSS.m_allTest.begin(); 01646 if ( m_allTest.end() == std::find(m_allTest.begin(), m_allTest.end(), *it) ) { 01647 m_allTest.splice( m_allTest.end(), SSS.m_allTest, it ); 01648 } 01649 else { 01650 SSS.m_allTest.pop_front(); // discards duplicate 01651 } 01652 } 01653 SSS.reset(); // reset counters 01654 } 01655 01656 #ifdef Spanish_dox 01657 /** Destructor. 01658 - Solo destruye aquellas pruebas que hayan sido agregadas con 01659 \c TestSuite<TestCase>::addTest(TestCase* T) (puntero). 01660 - No destruye las pruebas que fueron agregadas con 01661 \c TestSuite<TestCase>::addTest(TestCase& T) (referencia). 01662 */ 01663 #endif 01664 #ifdef English_dox 01665 /** Destructor. 01666 - Will destroy only those test that where addes with 01667 \c TestSuite<TestCase>::addTest(TestCase* T) (pointer). 01668 - Will not destroy those test that where addes with 01669 \c TestSuite<TestCase>::addTest(TestCase& T) (reference). 01670 */ 01671 #endif 01672 template <class TestCase> 01673 TestSuite<TestCase>::~TestSuite() { 01674 container_type::const_iterator it = m_allTest.begin(); 01675 while ( it != m_allTest.end() ) { 01676 if ( (*it)->m_test_suite_destroy ) { 01677 delete (*it); 01678 } 01679 ++it; 01680 } 01681 m_allTest.clear(); 01682 } 01683 01684 #ifdef Spanish_dox 01685 /** Invoca \c TestCase::run() para cada prueba en la colección. 01686 - No invoca los métodos \c TestCase::setUp() y \c TestCase::tearDown() 01687 cuando ejecuta cada prueba. 01688 - No invoca \c TestSuite<TestCase>::reset() antes de cada prueba. 01689 - Retorna \c "true" cuando todas las pruebas han tenido éxito (inclusive 01690 aquellas que fueron corridas antes de la invocación actual). 01691 */ 01692 #endif 01693 #ifdef English_dox 01694 /** Invokes \c TestCase::run() for each test in the collection. 01695 - Will not invoke methods \c TestCase::setUp() and \c TestCase::tearDown() 01696 when executing each test. 01697 - Will not invoke \c TestSuite<TestCase>::reset() before each test. 01698 - Returns \c "true" when al test have been successful (even those 01699 that were run before this invocation). 01700 */ 01701 #endif 01702 template <class TestCase> 01703 bool TestSuite<TestCase>::run() { 01704 bool res = true; 01705 container_type::const_iterator it = m_allTest.begin(); 01706 for ( ; it != m_allTest.end(); ++it ) { 01707 (*it)->run(); // hace la prueba 01708 } 01709 return wasSuccessful(); 01710 } 01711 01712 #ifdef Spanish_dox 01713 /** Invoca \c TestCase::runBare() para cada prueba en la colección. 01714 - Si invoca \c TestSuite<TestCase>::reset() antes de hacer cada prueba. 01715 - Si invoca \c TestCase::setUp() antes de cada prueba 01716 - Si invoca \c TestCase::tearDown() después de cada prueba. 01717 */ 01718 #endif 01719 #ifdef English_dox 01720 /** Invokes \c TestCase::runBare() for each test in the collection. 01721 - Will invoke \c TestSuite<TestCase>::reset() before each test. 01722 - Will invoke \c TestCase::setUp() before each test. 01723 - Will invoke \c TestCase::tearDown() after each test. 01724 */ 01725 #endif 01726 /** \dontinclude test_BUnit.cpp 01727 \skipline test::run() 01728 \until }} 01729 \see test_BUnit::test_run() 01730 */ 01731 template <class TestCase> 01732 void TestSuite<TestCase>::runBare() { 01733 bool res = true; 01734 container_type::const_iterator it = m_allTest.begin(); 01735 for ( ; it != m_allTest.end(); ++it ) { 01736 (*it)->reset(); // reset counters 01737 (*it)->setUp(); // setup test environment 01738 (*it)->run(); // run test 01739 (*it)->tearDown(); // reset test environment 01740 } 01741 } 01742 01743 template <class TestCase> 01744 int TestSuite<TestCase>::failureCount() const { 01745 int n; 01746 const_container_type::const_iterator it = m_allTest.begin(); 01747 for ( n = 0 ; it != m_allTest.end(); ++it ) { 01748 n += (*it)->failureCount(); 01749 } 01750 return n; 01751 /* NOTE: there is no choice but to count every test, as the client 01752 programmer could have run a test outside the collection, which 01753 would make counter TestSuite<TestCase>:m_failure to be outdated, 01754 because no mechanism is implemented for a "TestCase" to "tell" 01755 its "TestSuite<>" that it just executed "run()": 01756 */ 01757 #if 0 01758 class MyTest : public TestCase { ... }; 01759 TestSuite<TestCase> SSS; 01760 MyTest thisTest, *ptr_test = new MyTest; 01761 SSS.addTest( thisTest ); 01762 SSS.addTest( ptr_test ); 01763 SSS.run(); // exec [thisTest] + [*ptr_test] 01764 thisTest.run(); // exec [thisTest] ==> SSS ??? 01765 #endif 01766 /* NOTA: no queda más que contar todas las pruebas actuales, pues 01767 el programador cliente puede ejecutar alguna de las pruebas 01768 fuera de la colección, lo que haría que el contador 01769 TestSuite<TestCase>::m_failure quedara desactualizado, pues 01770 no está implementado un mecanismo para que el "TestCase" le 01771 "avise" a su "TestSuite<>" que acaba de ejecutar "run()". 01772 */ 01773 } 01774 01775 template <class TestCase> 01776 int TestSuite<TestCase>::successCount() const { 01777 int n; 01778 const_container_type::const_iterator it = m_allTest.begin(); 01779 for ( n = 0 ; it != m_allTest.end(); ++it ) { 01780 n += (*it)->successCount(); 01781 } 01782 return n; 01783 } 01784 01785 01786 template <class TestCase> 01787 void TestSuite<TestCase>::reset() { 01788 const_container_type::const_iterator it = m_allTest.begin(); 01789 for ( ; it != m_allTest.end(); ++it ) { 01790 (*it)->reset(); 01791 } 01792 } 01793 01794 #ifdef Spanish_dox 01795 /// Retorna un hilera que contiene el nombre, cantidad de éxitos y fallas. 01796 #endif 01797 #ifdef English_dox 01798 /// Returns a string with the name, number of successes and failures. 01799 #endif 01800 template <class TestCase> 01801 inline const std::string TestSuite<TestCase>::summary() const { 01802 typedef TestCase_is_base_for_TestSuite TC; 01803 std::string res = "TestSuite [" + getName() + ']'; 01804 res += " (OK: " + TC::toString( successCount() ) + ')'; 01805 res += " (FAIL: " + TC::toString( failureCount() ) + ')'; 01806 return res; 01807 } 01808 01809 template <class TestCase> 01810 const std::string TestSuite<TestCase>::toString() const { 01811 std::string failureString; 01812 TestSuite<TestCase>::container_type::const_iterator it; 01813 it = allTests().begin(); 01814 for ( ; it != allTests().end(); ++it ) { 01815 failureString += (*it)->toString() ; 01816 } 01817 return failureString; 01818 } 01819 01820 template <class TestCase> 01821 const std::string TestSuite<TestCase>::toXML() const { 01822 std::string XMLstring; 01823 TestSuite<TestCase>::container_type::const_iterator it; 01824 it = allTests().begin(); 01825 for ( ; it != allTests().end(); ++it ) { 01826 XMLstring += (*it)->toXML() ; 01827 } 01828 return XMLstring; 01829 } 01830 01831 /************************\ 01832 ************************** 01833 ** ** 01834 ** Macros ** 01835 ** ** 01836 ************************** 01837 \************************/ 01838 01839 01840 #ifdef Spanish_dox 01841 #endif 01842 #ifdef English_dox 01843 #endif 01844 01845 #ifdef BUnit_DEFINE_check_ok 01846 /* These are macros used by Adolfo to define the invariant for a 01847 class. Many times the invariant checking function check_ok() 01848 does not exist which makes these functions irrelevant: 01849 - http://www.di-mare.com/adolfo/p/Rep.htm#sc-02 01850 */ 01851 /* Estas son las macros usadas por Adolfo al definir la invariante 01852 de una clase. Muchas veces la función check_ok() usada para 01853 verificar invariante no existe, lo que hace irrelevantes estas 01854 definiciones: 01855 - http://www.di-mare.com/adolfo/p/Rep.htm#sc-02 01856 */ 01857 #ifdef Spanish_dox 01858 /// Declaración genérica para \c check_ok(). 01859 #endif 01860 #ifdef English_dox 01861 /// Generic declaration for \c check_ok(). 01862 #endif 01863 template <class T> bool check_ok( const T& ); 01864 inline bool check_ok( const double & ) { return true; } ///< <code>check_ok() == true</code> 01865 inline bool check_ok( const float & ) { return true; } ///< <code>check_ok() == true</code> 01866 inline bool check_ok( const long double & ) { return true; } ///< <code>check_ok() == true</code> 01867 inline bool check_ok( const signed char & ) { return true; } ///< <code>check_ok() == true</code> 01868 inline bool check_ok( const signed int & ) { return true; } ///< <code>check_ok() == true</code> 01869 inline bool check_ok( const signed long & ) { return true; } ///< <code>check_ok() == true</code> 01870 inline bool check_ok( const unsigned char & ) { return true; } ///< <code>check_ok() == true</code> 01871 inline bool check_ok( const unsigned int& ) { return true; } ///< <code>check_ok() == true</code> 01872 inline bool check_ok( const unsigned long & ) { return true; } ///< <code>check_ok() == true</code> 01873 #endif 01874 01875 #ifndef BUnit_DEFINE_check_ok // trick to make Doxygen document BUnit_DEFINE_check_ok 01876 #ifdef Spanish_dox 01877 /// Si esta macro existe las funciones \c check_ok() quedan definidas para los tipos básicos. 01878 #endif 01879 #ifdef English_dox 01880 /// If this macro exist functions for \c check_ok() will be defined for the basic types. 01881 #endif 01882 #define BUnit_DEFINE_check_ok 01883 #undef BUnit_DEFINE_check_ok 01884 #endif 01885 01886 #ifdef Spanish_dox 01887 /// Retorna una hilera \c std::string contruida desde el valor de \c val. 01888 /// - \c toString() with standard C++ 01889 #endif 01890 #ifdef English_dox 01891 /// Returns a \c std::string constructed form value \c val. 01892 /// - \c toString() with standard C++ 01893 #endif 01894 template <class T> 01895 std::string TestCase::toString( const T & val ) { 01896 // typedef basic_ostringstream<char> ostringstream; 01897 std::basic_ostringstream<char> temp; // ostringstream temp; 01898 temp << val; 01899 return temp.str( ); 01900 } 01901 01902 /// [CppUnit] Macros propios de \c CppUnit http://cppunit.sourceforge.net/doc/lastest 01903 #define CPPUNIT_BUnit() 01904 #undef CPPUNIT_BUnit 01905 01906 /// [CppUnit] Assertions that a condition is true. 01907 /// \see http://cppunit.sourceforge.net/doc/lastest/group___assertions.html#ga0 01908 #define CPPUNIT_ASSERT(condition) BUnit_TEST(condition) 01909 01910 /// [CppUnit] Assertion with a user specified message. 01911 /// \see http://cppunit.sourceforge.net/doc/lastest/group___assertions.html#ga1 01912 #define CPPUNIT_ASSERT_MESSAGE(message, condition) assertTrue_Msg(message,condition) 01913 01914 /// [CppUnit] Fails with the specified message. 01915 /// \see http://cppunit.sourceforge.net/doc/lastest/group___assertions.html#ga2 01916 #define CPPUNIT_FAIL(message) BUnit_FAILURE(message) 01917 01918 /// [CppUnit] Asserts that two values are equals. 01919 /// \see http://cppunit.sourceforge.net/doc/lastest/group___assertions.html#ga3 01920 #define CPPUNIT_ASSERT_EQUAL(expected, actual) BUnit_EQUAL(expected, actual) 01921 01922 /// [CppUnit] Asserts that two values are equals, provides additional messafe on failure. 01923 /// \see http://cppunit.sourceforge.net/doc/lastest/group___assertions.html#ga4 01924 #define CPPUNIT_ASSERT_EQUAL_MESSAGE(message, expected, actual) \ 01925 BUnit_EQUAL_Msg(message, expected, actual) 01926 01927 /// [CppUnit] Macro for primitive value comparisons. 01928 /// \see http://cppunit.sourceforge.net/doc/lastest/group___assertions.html#ga5 01929 #define CPPUNIT_ASSERT_DOUBLES_EQUAL(expected, actual, delta) \ 01930 assertEquals_Delta(expected, actual, delta) 01931 01932 /// [CppUnit] Asserts that the given expression throws an exception of the specified type. 01933 /// \see http://cppunit.sourceforge.net/doc/lastest/group___assertions.html#ga6 01934 #define CPPUNIT_ASSERT_THROW(expression, ExceptionType) \ 01935 do { \ 01936 bool cpputExceptionThrown_ = false; \ 01937 try { \ 01938 expression; \ 01939 } catch ( const ExceptionType & ) { \ 01940 cpputExceptionThrown_ = true; \ 01941 } \ 01942 \ 01943 if ( cpputExceptionThrown_ ) { \ 01944 break; \ 01945 } \ 01946 BUnit_FAILURE( \ 01947 "Expected exception: " #ExceptionType ) \ 01948 } while ( false ) 01949 01950 /// [CppUnit] Asserts that the given expression does not throw any exceptions. 01951 /// \see http://cppunit.sourceforge.net/doc/lastest/group___assertions.html#ga7 01952 #define CPPUNIT_ASSERT_NO_THROW(expression) \ 01953 do { \ 01954 try { \ 01955 expression; \ 01956 } catch ( ... ) { \ 01957 BUnit_FAILURE("Unexpected exception caught"); \ 01958 } \ 01959 } while ( false ) 01960 01961 /// [CppUnit] Asserts that an assertion fail. 01962 /// \see http://cppunit.sourceforge.net/doc/lastest/group___assertions.html#ga8 01963 #define CPPUNIT_ASSERT_ASSERTION_FAIL(assertion) \ 01964 CPPUNIT_ASSERT_THROW( assertion, CPPUNIT_NS::Exception ) 01965 01966 /// [CppUnit] Asserts that an assertion pass. 01967 /// \see http://cppunit.sourceforge.net/doc/lastest/group___assertions.html#ga9 01968 #define CPPUNIT_ASSERT_ASSERTION_PASS(assertion) \ 01969 CPPUNIT_ASSERT_NO_THROW( assertion ) 01970 01971 #define JUnit_BUnit() 01972 #undef JUnit_BUnit 01973 01974 /// [JUnit] Macros propios de \c JUnit http://junit.sourceforge.net/javadoc/junit/framework/Assert.html 01975 /// Asserts that two objects are equal. 01976 /// \see http://junit.sourceforge.net/javadoc/junit/framework/Assert.html#assertEquals(java.lang.Object,%20java.lang.Object) 01977 #define assertEquals( EXPECTED, ACTUAL ) BUnit_EQUAL(EXPECTED, ACTUAL) 01978 /// Asserts that two objects are equal (with message). 01979 /// \see http://junit.sourceforge.net/javadoc/junit/framework/Assert.html#assertEquals(java.lang.String,%20java.lang.Object,%20java.lang.Object) 01980 #define assertEquals_Msg( MSG, EXPECTED, ACTUAL ) BUnit_EQUAL_Msg(MSG, EXPECTED, ACTUAL) 01981 01982 /// [JUnit] Asserts that a condition is true. 01983 /// \see http://junit.sourceforge.net/javadoc/junit/framework/Assert.html#assertTrue(boolean) 01984 #define assertTrue( CONDITION ) \ 01985 testThis( CONDITION, #CONDITION, __FILE__, __LINE__ ) 01986 /// [JUnit] Asserts that a condition is true (with message). 01987 /// \see http://junit.sourceforge.net/javadoc/junit/framework/Assert.html#assertTrue(java.lang.String,%20boolean) 01988 #define assertTrue_Msg( MSG, CONDITION ) \ 01989 testThis( CONDITION, MSG, __FILE__, __LINE__ ) 01990 01991 /// [JUnit] Asserts that a condition is false. 01992 /// \see http://junit.sourceforge.net/javadoc/junit/framework/Assert.html#assertFalse(boolean) 01993 #define assertFalse( CONDITION ) \ 01994 testThis( !(CONDITION), "!(" #CONDITION ")", __FILE__, __LINE__ ) 01995 /// [JUnit] Asserts that a condition is false (with message). 01996 /// \see http://junit.sourceforge.net/javadoc/junit/framework/Assert.html#assertFalse(java.lang.String,%20boolean) 01997 #define assertFalse_Msg( MSG, CONDITION ) \ 01998 testThis( !(CONDITION), MSG, __FILE__, __LINE__ ) 01999 02000 #include <math.h> // fabs() 02001 /// [JUnit] Asserts that two doubles are equal concerning a delta. 02002 /// \see http://junit.sourceforge.net/javadoc/junit/framework/Assert.html#assertEquals(double,%20double,%20double) 02003 #define assertEquals_Delta(EXPECTED, ACTUAL, DELTA ) \ 02004 testThis( fabs( double(EXPECTED) - double(ACTUAL) ) < double(DELTA), \ 02005 "|" #EXPECTED "-" #ACTUAL "| < " #DELTA, __FILE__, __LINE__ ) 02006 02007 /// [JUnit] Asserts that two doubles are equal concerning a delta (with message). 02008 /// \see http://junit.sourceforge.net/javadoc/junit/framework/Assert.html#assertEquals(java.lang.String,%20double,%20double,%20double) 02009 #define assertEquals_Delta_Msg( MSG, EXPECTED, ACTUAL, DELTA ) \ 02010 testThis( fabs( double(EXPECTED) - double(ACTUAL) ) < double(DELTA), \ 02011 MSG, __FILE__, __LINE__ ) 02012 02013 /// [JUnit] Asserts that an object is null. 02014 /// \see http://junit.sourceforge.net/javadoc/junit/framework/Assert.html#assertNull(java.lang.Object) 02015 #define assertNull(OBJECT) \ 02016 testThis( 0==&(OBJECT), "assertNull(" #OBJECT ")", __FILE__, __LINE__ ) 02017 /// [JUnit] Asserts that an object isn't null. 02018 /// \see http://junit.sourceforge.net/javadoc/junit/framework/Assert.html#assertNotNull(java.lang.Object) 02019 #define assertNotNull(OBJECT) \ 02020 testThis( 0!=&(OBJECT), "assertNotNull(" #OBJECT ")", __FILE__, __LINE__ ) 02021 02022 /// [JUnit] Asserts that two objects refer to the same object. 02023 /// \see http://junit.sourceforge.net/javadoc/junit/framework/Assert.html#assertSame(java.lang.Object,%20java.lang.Object) 02024 #define assertSame(THIS, THAT) \ 02025 testThis( &(THIS)==&(THAT), \ 02026 "assertSame(" #THIS ", " #THAT ")", __FILE__, __LINE__ ) 02027 /// Asserts that two objects do not refer to the same object. 02028 /// \see http://junit.sourceforge.net/javadoc/junit/framework/Assert.html#assertNotSame(java.lang.Object,%20java.lang.Object) 02029 #define assertNotSame(THIS, THAT) \ 02030 testThis( &(THIS)!=&(THAT), \ 02031 "assertNotSame(" #THIS ", " #THAT ")", __FILE__, __LINE__ ) 02032 02033 #if 0 02034 // This breaks code as fail() is a method for streams. 02035 /// [JUnit] Fails a test with no message. 02036 /// \see http://junit.sourceforge.net/javadoc/junit/framework/Assert.html#fail() 02037 #define fail( ) BUnit_FAILURE("FAIL") 02038 #endif 02039 02040 /// [JUnit] Fails a test with the given message. 02041 /// \see http://junit.sourceforge.net/javadoc/junit/framework/Assert.html#fail(java.lang.String) 02042 #define fail_Msg( MSG ) BUnit_FAILURE(MSG) 02043 02044 #endif // BUnit_h 02045 02046 // EOF: BUnit.h