00001 // ADH_test.h (C) 2008 [email protected] 00002 00003 /** \file ADH_test.h 00004 \brief Módulo para prueba unitaria de programas. 00005 00006 \author Adolfo Di Mare <[email protected]> 00007 \date 2008 00008 */ 00009 00010 /** \mainpage 00011 00012 \section sec-01 Módulo para prueba unitaria de programas 00013 00014 El archivo de encabezado \c ADH_test.h apoya la escritura de módulos de prueba de 00015 unitaria programas. El modelo que se usa para esta implementación es 00016 similar al expuesto en este artículo "The Simplest Automated Unit 00017 Test Framework That Could Possibly Work" de Chuck Allison, que se 00018 puede obtener aquí: 00019 - http://www.stickyminds.com/getfile.asp?ot=XML&id=3129&fn=XDD3129filelistfilename1.pdf 00020 - http://www.google.com/search?num=100&as_q=Simplest+Unit+Test+Allison 00021 - http://search.yahoo.com/search?n=100&p=Simplest+Unit+Test+Allison 00022 00023 - Para simplificar al mínimo la tarea de programar los casos de prueba, 00024 la implementación completa de \c ADH_test está contenida en el archivo 00025 de encabezado \c ADH_test.h, por lo que para hacer pruebas basta poner 00026 esta directiva: 00027 - <strong>\#include "ADH_test.h"</strong> 00028 - Este marco de pruebas es similar a JUnit, pues se presume que en 00029 el futuro los estudiantes usarán Java como su lenguaje principal 00030 para desarrollo de programas (pues usan C++ sólo para adiestrarse 00031 profundamente en técnicas de programación). 00032 \see http://search.yahoo.com/search?n=100&p=JUnit+Java 00033 - Como el lenguaje C++ no tiene un mecanismo similar al de "reflexión" 00034 de Java, en cada prueba fallida se registra la condición de prueba 00035 exacta, obtenida a través de una invocación de la macro \c ADH_test_TEST() 00036 que registra el nombre del archivo \c __FILE__ y el renglón \c __LINE__ 00037 de la prueba. 00038 \see http://search.yahoo.com/search?n=100&p=reflection+Java 00039 - Para simplificar este marco de pruebas no se usa la clase \c TestResult 00040 que sirve para acumular resultados de las pruebas. En su lugar, se puede 00041 obtener una hilera enorme \c std::string que contiene el registro de 00042 todas las pruebas que no tuvieron éxito invocando el método 00043 \c TestCase::toString() o \c TestCase::toXML(). 00044 - Para simplificar esta plataforma de pruebas no se hace diferencia entre 00045 un caso de prueba de prueba existoso y uno que no tiene éxito porque no 00046 se ha levantado la excepción adecuada. Esto contrasta con JUnit, que 00047 llama "falla" a un caso de prueba que ha levantado la excepción equivocada. 00048 Por eso \c TestCase::failureCount() siempre retorna cero \c 0. 00049 \code 00050 // Falla vs Error en JUnit 00051 public void test_Falla () { 00052 try { 00053 new ArrayList(10).get( 11 ); 00054 fail("Falla si no tira IndexOutOfBoundsException" ); // falla 00055 } 00056 catch (IndexOutOfBoundsException success) { } // Ok 00057 } 00058 public void test_Error() { 00059 assertTrue( 1 == 2 ); // error 00060 } 00061 \endcode 00062 - En \c ADH_test.h no se hace diferencia entre "fallas" y "errores". 00063 - En \c JUnit una "falla" se produce cuando no se levanta la excepción 00064 adecuada. 00065 - En \c JUnit un "error" se produce cuando una aserción resulta falsa. 00066 - \see http://osdir.com/ml/java.junit.user/2002-06/msg00114.html 00067 - \see http://www.cs.waikato.ac.nz/~bernhard/314/junit3.8.1/doc/faq/faq.htm#tests_9 00068 - \see http://search.yahoo.com/search?n=100&p=junit+difference+failure+error 00069 - En JUnit la clase \c TestCase es una subclase de \c Assert; aquí no existe 00070 la clase \c Assert pero para mantener una leve compatibiliidad sí se provée 00071 una funcionalidad similar con macros cuyo nombres comienzan con "assert". 00072 \see http://search.yahoo.com/search?n=100&p=JUnit+Java+Assert+method 00073 00074 \dontinclude test_ADH_test.cpp 00075 \skipline test::Allison() 00076 \until }} 00077 \see test_ADH_test::test_Allison() 00078 */ 00079 00080 #ifndef ADH_test_h 00081 #define ADH_test_h ///< Evita la inclusión múltiple 00082 00083 #include <list> // std::list 00084 #include <string> // class std::string 00085 #include <sstream> // class basic_ostringstream<T,Ch> 00086 #include <cstdio> // memcpy()+strlen() 00087 #include <typeinfo> // class std::type_info ==> char* typeid().name(); 00088 #include <algorithm> // find() 00089 00090 // using namespace std; 00091 /// Definido por la biblioteca C++ estándar. 00092 namespace std {} // Está acá para que Doxygen lo documente 00093 00094 /// Escuela de Ciencias de la Computación e Informática. 00095 /// \see http:www.ecci.ucr.ac.cr 00096 namespace ECCI { } 00097 00098 /// Clase privada que contiene los datos de cada prueba no exitosa. 00099 class TestCaseError { 00100 const char * m_fname; ///< Nombre del archivo en donde se produjo el error. 00101 int m_lineno; ///< Número de línea del archivo en donde se produjo el error. 00102 const char * m_label; ///< Mensaje descriptivo del error. 00103 bool m_destroy_label; ///< Indica si el destructor debe retornar la memoria de \c m_label. 00104 private: 00105 TestCaseError() : 00106 m_fname(""), m_lineno(0), m_label(""), m_destroy_label(false) 00107 { } ///< Constructor por defecto. 00108 TestCaseError(const char * fname, int line, const char * label, bool destroy ) 00109 : m_fname(fname), m_lineno(line), m_label(label), m_destroy_label(destroy) 00110 { } ///< Constructor. 00111 public: 00112 ~TestCaseError() { if (m_destroy_label) { delete [] m_label; } } ///< Destructor. 00113 TestCaseError( const TestCaseError& o ) { 00114 m_fname = o.m_fname; m_lineno = o.m_lineno; m_label = o.m_label; 00115 m_destroy_label = o.m_destroy_label; 00116 const_cast<TestCaseError*>(&o)->m_destroy_label = false; // evita doble destrucción de m_label 00117 // const_cast<bool>(o.m_destroy_label) = false; // no compila 00118 } ///< Constructor de copia. 00119 void operator = ( TestCaseError& o ) { 00120 m_fname = o.m_fname; m_lineno = o.m_lineno; m_label = o.m_label; 00121 m_destroy_label = o.m_destroy_label; 00122 o.m_destroy_label = false; // evita doble destrucción de m_label 00123 } ///< Copiador usado al insertar en el contenedor. 00124 friend class TestCase; ///< Caso de prueba. 00125 template <class TestCase> friend void do_toXML( const TestCase * tc , std::basic_ostringstream<char> & ost ); 00126 template <class TestCase> friend void do_toString( const TestCase * tc , std::basic_ostringstream<char> & ost ); 00127 }; // TestCaseError 00128 00129 /// Cada caso de prueba es una instancia derivada de esta clase abstracta. 00130 /// - Siempre es obligatorio implementar \c TestCase::run(). 00131 class TestCase { 00132 protected: 00133 int m_pass; ///< Cantidad de pruebas exitosas 00134 int m_error; ///< Cantidad de pruebas que han producido error 00135 const char * m_name; ///< Nombre del caso de prueba 00136 bool m_test_suite_destroy; ///< Indica si la prueba está en memoria dinámica. 00137 /// Contenedor para registrar las pruebas que han producido error. 00138 std::list<TestCaseError> m_errorList; 00139 public: 00140 TestCase(const char * name=0); 00141 virtual ~TestCase() { } ///< Destructor 00142 /// <strong>[virtual]</strong> ==> Ejecuta la prueba y retorna \c "false" si produce error. 00143 /// <strong>[***]</strong> Siempre es necesario redefinir el método \c run(). 00144 /// \see runBare(). 00145 virtual bool run() = 0; 00146 void runBare(); 00147 bool Run() { return run(); } ///< Sinónimo de \c run() 00148 bool runTest() { return run(); } ///< Sinónimo de \c run() 00149 virtual void setUp(); 00150 virtual void tearDown(); 00151 int countTestCases() const { return 1; } ///< Cantidad de casos de prueba que serán ejecutados. 00152 /// Cantidad total de pruebas realizadas. 00153 /// - Sinónimo de <code>successCount()+errorCount()+failureCount()</code>. 00154 /// \see reset(). 00155 int runCount() const { return successCount()+errorCount(); } 00156 /// Cantidad de pruebas que han producido error. \see reset(). 00157 virtual int errorCount() const { return m_error; } 00158 /// Siempre retorna \c 0 (cero): "Cantidad de fallas". 00159 /// - ADH_test no hace diferencia entre "errores" y "fallas" 00160 /// \see http://osdir.com/ml/java.junit.user/2002-06/msg00114.html 00161 int failureCount() const { return 0; } 00162 virtual int successCount() const { return m_pass; } ///< Cantidad de pruebas exitosas. \see reset(). 00163 /// Retorna \c "true" si todas las pruebas han sido exitosas. 00164 /// - Sinónimo de <code>(successCount() == runCount())</code> 00165 bool wasSuccessful() const { return successCount() == runCount(); } 00166 virtual void reset(); 00167 public: 00168 /// Obtiene el nombre de la prueba. \see setName(). 00169 std::string getName() const; 00170 void setName( const char * name=0 ); 00171 virtual const std::string toString() const; 00172 virtual const std::string summary() const; 00173 virtual const std::string toXML() const; 00174 /// Retorna la hilera encabezado \c summary() seguido de errores \c toString(). 00175 const std::string report() const { return summary() + '\n' + toString(); } 00176 const std::string errorString() const { return toString(); } ///< Sinónimo de \c toString() 00177 template <class T> static std::string toString( const T & val ); 00178 protected: 00179 void recordSuccess() { ++m_pass; } ///< Registra como exitoso el resultado de una prueba 00180 void recordError( const char* label, const char* fname, int lineno, bool must_copy=false); 00181 void recordError( const std::string& label, const char* fname, int lineno ); 00182 void testThis( bool cond, const std::string& label, const char* fname, long lineno); 00183 void testThis( bool cond, const char* label, const char* fname, long lineno, bool must_copy=false); 00184 template <class TestCase> friend void do_toXML( const TestCase * tc , std::basic_ostringstream<char> & ost ); 00185 template <class TestCase> friend void do_toString( const TestCase * tc , std::basic_ostringstream<char> & ost ); 00186 template <class TestCase> friend class TestSuite; ///< Colección de pruebas. 00187 int nPass() const { return m_pass; } ///< Sinónimo de \c successCount() [OBSOLETO] \deprecated 00188 int nError() const { return m_error; } ///< Sinónimo de \c errorCount() [OBSOLETO] \deprecated 00189 private: 00190 virtual bool iAmTestSuite() const { return false; } ///< Retorna \c false para \c TestCase. 00191 TestCase(const TestCase&); ///< \c "private" evita la copia de casos de prueba 00192 TestCase& operator=(const TestCase&); ///< \c "private" evita la copia de casos de prueba 00193 friend class test_ADH_test; ///< Clase de prueba para \c ADH_test.h 00194 }; // TestCase 00195 00196 /// NO IMPLEMENTADO ==> Colección de pruebas. 00197 template <class TC> class TestSuite : public TestCase { }; 00198 00199 /** Constructor. 00200 - Si no se indica el nombre en \c "name", el nombre se obtiene con <code>typeid(*this).name()</code>. 00201 00202 \dontinclude test_ADH_test.cpp 00203 \skipline test::constructor() 00204 \until }} 00205 \see test_ADH_test::test_constructor() 00206 */ 00207 inline TestCase::TestCase(const char * name) : 00208 m_pass(0), m_error(0), m_name(name), m_test_suite_destroy(false), m_errorList() { } 00209 00210 /** Elimina todas las pruebas realizadas. 00211 - Anula los contadores de pruebas porque deja la clase en el estado 00212 inicial que tuvo al ser construida. 00213 - Borra el registro de pruebas no exitosas. 00214 - No borra el nombre de la prueba. 00215 00216 \dontinclude test_ADH_test.cpp 00217 \skipline test::reset() 00218 \until }} 00219 \see test_ADH_test::test_reset() 00220 */ 00221 inline void TestCase::reset() { 00222 m_pass = m_error = 0; 00223 m_errorList.clear(); 00224 } 00225 00226 inline std::string TestCase::getName() const { 00227 return ( m_name != 0 ? m_name : typeid(*this).name() ); 00228 } 00229 00230 /** Le cambia el nombre a la prueba. 00231 \dontinclude test_ADH_test.cpp 00232 \skipline test::setName() 00233 \until }} 00234 \see test_ADH_test::test_setName() 00235 */ 00236 inline void TestCase::setName( const char * name ) { 00237 m_name = name; 00238 } 00239 00240 /** Ejecuta la prueba <code>setUp(); run(); tearDown();</code>. 00241 - A diferencia de \c run(), este método si establece el ambiente 00242 de prueba invocando \c setUp() y \c tearDown() antes y después 00243 de hacer la prueba. 00244 00245 \dontinclude test_ADH_test.cpp 00246 \skipline test::run() 00247 \until }} 00248 \see test_ADH_test::test_run() 00249 */ 00250 inline void TestCase::runBare( ) { setUp(); run(); tearDown(); } 00251 00252 /// Establece el ambiente para la ejecución de la prueba 00253 /// \see TestCase::setUp() 00254 typedef TestCase TestFixture; 00255 00256 /** Establece el ambiente en que se realizará cada prueba. 00257 - Como \c TestCase::run() es un método abstracto, 00258 para facilitar la programación lo usual es que el 00259 programador no incluya invocaciones a 00260 \c TestCase::setUp() y \c TestCase::tearDown() 00261 pues es más simple dejar que lo haga 00262 \c TestSuite<TestCase>::runBare(). 00263 - A diferencia de \c TestCase::runBare(), el método 00264 \c TestCase::run() no establece el ambiente de prueba 00265 porque no invoca ni a \c TestCase::setUp() antes de 00266 la prueba ni a \c TestCase::tearDown() después . 00267 - \c TestSuite<TestCase>::runBare() invoca los métodos 00268 \c TestCase::setUp() y \c TestCase::tearDown() 00269 cuando ejecuta cada prueba. 00270 - Por eso, si el programador cliente quiere que cada 00271 prueba se ejecute luego de establecer el ambiente de 00272 la prueba, lo más práctico es que agregue sus 00273 pruebas a una colección de pruebas \c TestSuite para 00274 ejecutarlas con \c TestSuite<TestCase>::runBare(). 00275 */ 00276 inline void TestCase::setUp() { } 00277 00278 /// Destruye el ambiente de prueba 00279 inline void TestCase::tearDown() {} 00280 00281 /** Efectúa la prueba y registra el resultado. 00282 - Si la prueba es exitosa sólo incrementa la cantidad de éxitos \c successCount(). 00283 - Si la prueba no tiene éxito reporta en \c toString() el hecho. 00284 - La prueba es \c "cond". 00285 - Los valores \c "fname" y \c "lineno" indican el archivo y el renglón 00286 en donde se ejecuta la prueba. 00287 - Usualmente los valores de \c "fname" y \c "lineno" se obtienen con 00288 las macros globales \c "__FILE__" y \c "__LINE__". 00289 - El valor \c "must_copy" indica que es necesario hacer una copia de la 00290 hilera \c "label", copia que será destruida cuando el registro de 00291 pruebas no exitosas sea borrado. 00292 - En la mayor parte de los casos, la hilera \c "label" es una constante 00293 generada por el preprocesador al usar la macro \c \#cond y por eso su 00294 memoria no debe ser retornada. 00295 00296 Este método es invocado usando la macro \c ADH_test_TEST(). 00297 \dontinclude test_ADH_test.cpp 00298 \skipline test::testThis() 00299 \until }} 00300 \see test_ADH_test::test_testThis() 00301 */ 00302 inline void TestCase::testThis( bool cond, const char * label, const char* fname, long lineno, bool must_copy ) { 00303 if (cond) { 00304 recordSuccess(); 00305 } 00306 else { 00307 recordError( label, fname, lineno, must_copy ); 00308 } 00309 } 00310 00311 inline void TestCase::testThis( bool cond, const std::string& label, const char* fname, long lineno ) { 00312 testThis( cond, label.c_str(), fname, lineno, true /* must_copy == true */ ); 00313 } ///< Sinónimo de \c testThis(); 00314 00315 /** Registra que la prueba no tuvo éxito. 00316 - Los valores \c "fname" y \c "lineno" indican el archivo y el renglón 00317 en donde se ejecuta la prueba. 00318 - Usualmente los valores de \c "fname" y \c "lineno" se obtienen con 00319 las macros globales \c "__FILE__" y \c "__LINE__". 00320 - El valor \c "must_copy" indica que es necesario hacer una copia de la 00321 hilera \c "label", copia que será destruida cuando el registro de 00322 pruebas no exitosas sea borrado. 00323 - En la mayor parte de los casos, la hilera \c "label" es una constante 00324 generada por el preprocesador al usar la macro \c \#cond y por eso su 00325 memoria no debe ser retornada. 00326 00327 Este método es invocado usando la macro \c ADH_test_ERROR(). 00328 */ 00329 inline void TestCase::recordError( const char* label, const char* fname, int lineno, bool must_copy ) { 00330 if ( must_copy ) { 00331 size_t len = strlen(label)+1; 00332 char* str = new char[ len ]; // hace la copia del mensaje de error 00333 memcpy( str, label, len ); 00334 label = str; 00335 } 00336 m_errorList.push_back( TestCaseError ( fname, lineno, label, must_copy ) ); 00337 m_error++; 00338 } 00339 00340 /// Registra que la prueba no tuvo éxito. 00341 /// - En \c ADH_test.h no se hace diferencia entre "fallas" y "errores". 00342 inline void TestCase::recordError( const std::string& label, const char* fname, int lineno ) { 00343 recordError( label.c_str(), fname, lineno, true /* must_copy == true */ ); 00344 /* Nota: como aquí se obtiene memoria dinámica para "str" hay que marcar 00345 el campo "TestCase::m_destroy_label" con el valor "true" de manera 00346 que el destructor de "TestCaseError" retorne esa memoria. 00347 */ 00348 } 00349 00350 /** Hilera "enooorme" que contiene copia del registro de pruebas no exitosas, separados por \c "\n". 00351 \code 00352 =\_error: 1 == 0 00353 =/ (125) X:\DIR\SubDir\test_ADH_test.cpp 00354 =\_error: 4 == 0 00355 =/ (128) X:\DIR\SubDir\test_ADH_test.cpp 00356 \endcode 00357 */ 00358 inline const std::string TestCase::toString() const { 00359 // typedef basic_ostringstream<char> ostringstream; 00360 std::basic_ostringstream<char> ost; // ostringstream ost; 00361 do_toString( this , ost ); 00362 return ost.str(); 00363 } 00364 00365 /// Le agrega a \c ost la hilera de todas las pruebas no exitosas de \c *tc. 00366 template <class TestCase> 00367 void do_toString( const TestCase * tc , std::basic_ostringstream<char> & ost ) { 00368 std::list<TestCaseError>::const_iterator it = tc->m_errorList.begin(); 00369 for ( ; it != tc->m_errorList.end(); ++it) { 00370 ost << "=\\_error: " << it->m_label << " \n=/ (" 00371 << it->m_lineno << ") " << it->m_fname << "\n"; 00372 } 00373 return; 00374 /* NOTA 00375 La implementación de "TestCase::toString()" está hecha invocando esta 00376 función emplantillada para que sea el compilador el responsable de 00377 remover versiones duplicadas de esta misma rutina, las que se producen 00378 cuando este archivo de encabezado ("ADH_test.h") es incluido en varios 00379 archivos "*.cpp". Todo esto hay que hacerlo para que "ADH_test.h" quepa, 00380 completo, en un único archivo de encabezado. 00381 */ 00382 } 00383 00384 /** Hilera XML que contiene una copia de las pruebas no exitosas. 00385 \code 00386 <error file="X:\DIR\SubDir\test_ADH_test.cpp" line="125" message="1 == 0"/> 00387 <error file="X:\DIR\SubDir\test_ADH_test.cpp" line="128" message="4 == 0"/> 00388 \endcode 00389 */ 00390 inline const std::string TestCase::toXML() const { 00391 // typedef basic_ostringstream<char> ostringstream; 00392 std::basic_ostringstream<char> ost; // ostringstream ost; 00393 do_toXML( this , ost ); 00394 return ost.str(); 00395 } 00396 00397 /// Le agrega a \c ost la hilera de todas las pruebas no exitosas de \c *tc en formato XML. 00398 template <class TestCase> 00399 void do_toXML( const TestCase * tc , std::basic_ostringstream<char> & ost ) { 00400 std::list<TestCaseError>::const_iterator it = tc->m_errorList.begin(); 00401 for ( ; it != tc->m_errorList.end(); ++it ) { 00402 ost << "<error file=\"" << it->m_fname 00403 << "\" line=\"" << it->m_lineno 00404 << "\" message=\"" << it->m_label << "\"/>" << std::endl; 00405 } 00406 return; 00407 /* Nota: 00408 La implementación de "TestCase::toXML()" está hecha invocando a la 00409 función emplantillada "do_toXML()" para que el compilador se encargue 00410 de evitar la declaración múltiple que ocurre cuando "ADH_test.h" es 00411 incluido en varios archivos "*.cpp" diferentes en el mismo proyecto. 00412 */ 00413 } 00414 00415 /// [ADH_test] Macros propios de \c ADH_test.h 00416 #define TEST_ADH_test() 00417 #undef TEST_ADH_test 00418 00419 /** [ADH_test] Efectúa la prueba \c "cond y registra el resultado. 00420 - Es más elegante usar assertTrue() que hace lo mismo. 00421 - Si la prueba \c "cond" tiene éxito invoca el método 00422 \c TestCase::recordSuccess(). 00423 - Si la prueba \c "cond" no tiene éxito invoca el método 00424 \c TestCase::recordError(). 00425 - Esta es una una macro que invoca el método 00426 \c TestCase::testThis(). 00427 00428 \dontinclude test_ADH_test.cpp 00429 \skipline test::ADH_test_macro() 00430 \until }} 00431 \see test_ADH_test::test_ADH_test_macro() 00432 */ 00433 #define ADH_test_TEST(cond) testThis( cond, #cond, __FILE__, __LINE__ ) 00434 00435 /// [ADH_test] Macro similar a \c ADH_test_TEST() que usa el mensaje \c "msg". 00436 /// - El mensaje \c "msg" debe ser una hilera literal o un objeto que pueda 00437 /// convertirse en <code>(const char *)</code>. 00438 #define ADH_test_TEST_Msg(msg, cond) testThis( cond, msg, __FILE__, __LINE__ ) 00439 00440 /** [ADH_test] Registra como "error" el resultado de una prueba. 00441 - El programador cliente es quien determinó que la prueba 00442 no tuvo éxito y por eso quiere registrar ese hecho. 00443 - Está implementado comun una macro que invoca 00444 el método \c TestCase::recordError(). 00445 00446 \see ADH_test_TEST() 00447 \code 00448 if (22==33) { 00449 ADH_test_ERROR("! (22==33)"); // Registra el error 00450 } 00451 \endcode 00452 */ 00453 #define ADH_test_ERROR(msg) recordError( msg, __FILE__, __LINE__ ) 00454 00455 /** [ADH_test] Registra como "exitoso" el resultado de una prueba. 00456 - El programador cliente es quien determinó que la prueba 00457 fue exitosa y por eso quiere registrar ese hecho. 00458 - Generalmente se usa después de atrapar una excepción que 00459 se supone debió ser lanzada como resultado de la prueba. 00460 - Está implementado comun una macro que invoca 00461 el método \c TestCase::recordSuccess(). 00462 \see ADH_test_TEST() 00463 */ 00464 #define ADH_test_SUCCESS() recordSuccess() 00465 00466 /// [ADH_test] Efectúa la prueba para determinar si <code>(expected == actual)</code>. 00467 /// - Si la prueba tiene éxito invoca el método 00468 /// \c TestCase::recordSuccess(). 00469 /// - Si la prueba no tiene éxito invoca el método 00470 /// \c TestCase::recordError(). 00471 /// - Esta es una una macro que invoca el método 00472 /// \c TestCase::testThis(). 00473 /// \see ADH_test_TEST() 00474 #define ADH_test_EQUAL(expected, actual) \ 00475 testThis( (expected) == (actual), #expected " == " #actual, __FILE__, __LINE__ ) 00476 00477 /// [ADH_test] Efectúa la prueba para determinar si <code>expected == actual</code>. 00478 /// - Si la prueba tiene éxito invoca el método 00479 /// \c TestCase::recordSuccess(). 00480 /// - Si la prueba no tiene éxito invoca el método 00481 /// \c TestCase::recordError(). 00482 /// - Esta es una una macro que invoca el método 00483 /// \c TestCase::testThis(). 00484 /// - Registra el mensaje \c "MSG" si la prueba no tiene éxito. 00485 /// \see ADH_test_TEST() 00486 #define ADH_test_EQUAL_Msg(MSG, expected, actual) \ 00487 testThis( (expected) == (actual), MSG, __FILE__, __LINE__ ) 00488 00489 /// Retorna un hilera que contiene el nombre, cantidad de éxitos y cantidad de errores de la prueba. 00490 inline const std::string TestCase::summary() const { 00491 std::string res = "TestCase [" + getName() + ']'; 00492 res += " (OK: " + TestCase::toString( successCount() ) + ')'; 00493 res += " (ERROR: " + TestCase::toString( errorCount() ) + ')'; 00494 return res; 00495 } 00496 00497 // ¿¿¿ TestSuite ??? 00498 00499 //inline bool check_ok<int>( const int & ) { return true; } 00500 //template<class unsigned> inline bool check_ok( const unsigned & ) { return true; } 00501 //template<class int> inline bool check_ok( const long & ) { return true; } 00502 //template<class int> inline bool check_ok( const flota & ) { return true; } 00503 //template<class int> inline bool check_ok( const double & ) { return true; } 00504 00505 template <class T> bool check_ok( const T& ); ///< Declaración genérica para \c check_ok() 00506 inline bool check_ok( const signed char & ) { return true; } ///< \c check_ok<>()==true por defecto (por si el programador no lo ha implementado) 00507 inline bool check_ok( const unsigned char & ) { return true; } ///< \c check_ok<>()==true por defecto (por si el programador no lo ha implementado) 00508 inline bool check_ok( const signed int & ) { return true; } ///< \c check_ok<>()==true por defecto (por si el programador no lo ha implementado) 00509 inline bool check_ok( const unsigned int& ) { return true; } ///< \c check_ok<>()==true por defecto (por si el programador no lo ha implementado) 00510 inline bool check_ok( const signed long & ) { return true; } ///< \c check_ok<>()==true por defecto (por si el programador no lo ha implementado) 00511 inline bool check_ok( const unsigned long & ) { return true; } ///< \c check_ok<>()==true por defecto (por si el programador no lo ha implementado) 00512 inline bool check_ok( const float & ) { return true; } ///< \c check_ok<>()==true por defecto (por si el programador no lo ha implementado) 00513 inline bool check_ok( const double & ) { return true; } ///< \c check_ok<>()==true por defecto (por si el programador no lo ha implementado) 00514 inline bool check_ok( const long double & ) { return true; } ///< \c check_ok<>()==true por defecto (por si el programador no lo ha implementado) 00515 00516 /// Retorna una hilera que contiene el valor de \c val. 00517 /// - \c toString() with standard C++ 00518 template <class T> 00519 std::string TestCase::toString( const T & val ) { 00520 // typedef basic_ostringstream<char> ostringstream; 00521 std::basic_ostringstream<char> temp; // ostringstream temp; 00522 temp << val; 00523 return temp.str( ); 00524 } 00525 00526 /// [CppUnit] Macros propios de \c CppUnit http://cppunit.sourceforge.net/doc/lastest 00527 #define CPPUNIT_ADH_test() 00528 #undef CPPUNIT_ADH_test 00529 00530 /// [CppUnit] Assertions that a condition is true. 00531 /// \see http://cppunit.sourceforge.net/doc/lastest/group___assertions.html#ga0 00532 #define CPPUNIT_ASSERT(condition) ADH_test_TEST(condition) 00533 00534 /// [CppUnit] Assertion with a user specified message. 00535 /// \see http://cppunit.sourceforge.net/doc/lastest/group___assertions.html#ga1 00536 #define CPPUNIT_ASSERT_MESSAGE(message, condition) CPPUNIT_ASSERT(condition) 00537 00538 /// [CppUnit] Fails with the specified message. 00539 /// \see http://cppunit.sourceforge.net/doc/lastest/group___assertions.html#ga2 00540 #define CPPUNIT_FAIL(message) ADH_test_ERROR(message) 00541 00542 /// [CppUnit] Asserts that two values are equals. 00543 /// \see http://cppunit.sourceforge.net/doc/lastest/group___assertions.html#ga3 00544 #define CPPUNIT_ASSERT_EQUAL(expected, actual) ADH_test_EQUAL(expected, actual) 00545 00546 /// [CppUnit] Asserts that two values are equals, provides additional messafe on failure. 00547 /// \see http://cppunit.sourceforge.net/doc/lastest/group___assertions.html#ga4 00548 #define CPPUNIT_ASSERT_EQUAL_MESSAGE(message, expected, actual) \ 00549 ADH_test_EQUAL_Msg(message, expected, actual) 00550 00551 /// [CppUnit] Macro for primitive value comparisons. 00552 /// \see http://cppunit.sourceforge.net/doc/lastest/group___assertions.html#ga5 00553 #define CPPUNIT_ASSERT_DOUBLES_EQUAL(expected, actual, delta) \ 00554 assertEquals_Delta(expected, actual, delta) 00555 00556 /// [CppUnit] Asserts that the given expression throws an exception of the specified type. 00557 /// \see http://cppunit.sourceforge.net/doc/lastest/group___assertions.html#ga6 00558 #define CPPUNIT_ASSERT_THROW(expression, ExceptionType) \ 00559 do { \ 00560 bool cpputExceptionThrown_ = false; \ 00561 try { \ 00562 expression; \ 00563 } catch ( const ExceptionType & ) { \ 00564 cpputExceptionThrown_ = true; \ 00565 } \ 00566 \ 00567 if ( cpputExceptionThrown_ ) { \ 00568 break; \ 00569 } \ 00570 ADH_test_ERROR( \ 00571 "Expected exception: " #ExceptionType ) \ 00572 } while ( false ) 00573 00574 /// [CppUnit] Asserts that the given expression does not throw any exceptions. 00575 /// \see http://cppunit.sourceforge.net/doc/lastest/group___assertions.html#ga7 00576 #define CPPUNIT_ASSERT_NO_THROW(expression) \ 00577 do { \ 00578 try { \ 00579 expression; \ 00580 } catch ( ... ) { \ 00581 ADH_test_ERROR("Unexpected exception caught"); \ 00582 } \ 00583 } while ( false ) 00584 00585 /// [CppUnit] Asserts that an assertion fail. 00586 /// \see http://cppunit.sourceforge.net/doc/lastest/group___assertions.html#ga8 00587 #define CPPUNIT_ASSERT_ASSERTION_FAIL(assertion) \ 00588 CPPUNIT_ASSERT_THROW( assertion, CPPUNIT_NS::Exception ) 00589 00590 /// [CppUnit] Asserts that an assertion pass. 00591 /// \see http://cppunit.sourceforge.net/doc/lastest/group___assertions.html#ga9 00592 #define CPPUNIT_ASSERT_ASSERTION_PASS(assertion) \ 00593 CPPUNIT_ASSERT_NO_THROW( assertion ) 00594 00595 // /// Concatena la hilera \c THIS con la hilera \c THAT 00596 // #define ADH_test_CAT( THIS, THAT ) (std::string(THIS) + std::string(THAT).c_str()) 00597 00598 #define JUnit_ADH_test() 00599 #undef JUnit_ADH_test 00600 00601 /// [JUnit] Macros propios de \c JUnit http://junit.sourceforge.net/javadoc/junit/framework/Assert.html 00602 /// Asserts that two objects are equal. 00603 /// \see http://junit.sourceforge.net/javadoc/junit/framework/Assert.html#assertEquals(java.lang.Object,%20java.lang.Object) 00604 #define assertEquals( EXPECTED, ACTUAL ) ADH_test_EQUAL(EXPECTED, ACTUAL) 00605 /// Asserts that two objects are equal (with message). 00606 /// \see http://junit.sourceforge.net/javadoc/junit/framework/Assert.html#assertEquals(java.lang.String,%20java.lang.Object,%20java.lang.Object) 00607 #define assertEquals_Msg( MSG, EXPECTED, ACTUAL ) ADH_test_EQUAL_Msg(MSG, EXPECTED, ACTUAL) 00608 00609 /// [JUnit] Asserts that a condition is true. 00610 /// \see http://junit.sourceforge.net/javadoc/junit/framework/Assert.html#assertTrue(boolean) 00611 #define assertTrue( CONDITION ) testThis( CONDITION, #CONDITION, __FILE__, __LINE__ ) 00612 /// [JUnit] Asserts that a condition is true (with message). 00613 /// \see http://junit.sourceforge.net/javadoc/junit/framework/Assert.html#assertTrue(java.lang.String,%20boolean) 00614 #define assertTrue_Msg( MSG, CONDITION ) testThis( CONDITION, MSG, __FILE__, __LINE__ ) 00615 00616 /// [JUnit] Asserts that a condition is false. 00617 /// \see http://junit.sourceforge.net/javadoc/junit/framework/Assert.html#assertFalse(boolean) 00618 #define assertFalse( CONDITION ) testThis( !(CONDITION), "!(" #CONDITION ")", __FILE__, __LINE__ ) 00619 /// [JUnit] Asserts that a condition is false (with message). 00620 /// \see http://junit.sourceforge.net/javadoc/junit/framework/Assert.html#assertFalse(java.lang.String,%20boolean) 00621 #define assertFalse_Msg( MSG, CONDITION ) testThis( !(CONDITION), MSG, __FILE__, __LINE__ ) 00622 00623 #include <math.h> // fabs() 00624 /// [JUnit] Asserts that two doubles are equal concerning a delta. 00625 /// \see http://junit.sourceforge.net/javadoc/junit/framework/Assert.html#assertEquals(double,%20double,%20double) 00626 #define assertEquals_Delta(EXPECTED, ACTUAL, DELTA ) \ 00627 testThis( fabs( double(EXPECTED) - double(ACTUAL) ) < double(DELTA), \ 00628 "|" #EXPECTED "-" #ACTUAL "| < " #DELTA, __FILE__, __LINE__ ) 00629 00630 /// [JUnit] Asserts that two doubles are equal concerning a delta (with message). 00631 /// \see http://junit.sourceforge.net/javadoc/junit/framework/Assert.html#assertEquals(java.lang.String,%20double,%20double,%20double) 00632 #define assertEquals_Delta_Msg( MSG, EXPECTED, ACTUAL, DELTA ) \ 00633 testThis( fabs( double(EXPECTED) - double(ACTUAL) ) < double(DELTA), \ 00634 MSG, __FILE__, __LINE__ ) 00635 00636 /// [JUnit] Asserts that an object is null. 00637 /// \see http://junit.sourceforge.net/javadoc/junit/framework/Assert.html#assertNull(java.lang.Object) 00638 #define assertNull(OBJECT) testThis( 0==&(OBJECT), "assertNull(" #OBJECT ")", __FILE__, __LINE__ ) 00639 /// [JUnit] Asserts that an object isn't null. 00640 /// \see http://junit.sourceforge.net/javadoc/junit/framework/Assert.html#assertNotNull(java.lang.Object) 00641 #define assertNotNull(OBJECT) testThis( 0!=&(OBJECT), "assertNotNull(" #OBJECT ")", __FILE__, __LINE__ ) 00642 00643 /// [JUnit] Asserts that two objects refer to the same object. 00644 /// \see http://junit.sourceforge.net/javadoc/junit/framework/Assert.html#assertSame(java.lang.Object,%20java.lang.Object) 00645 #define assertSame(THIS, THAT) testThis( &(THIS)==&(THAT), "assertSame(" #THIS ", " #THAT ")", __FILE__, __LINE__ ) 00646 /// Asserts that two objects do not refer to the same object. 00647 /// \see http://junit.sourceforge.net/javadoc/junit/framework/Assert.html#assertNotSame(java.lang.Object,%20java.lang.Object) 00648 #define assertNotSame(THIS, THAT) testThis( &(THIS)!=&(THAT), "assertNotSame(" #THIS ", " #THAT ")", __FILE__, __LINE__ ) 00649 00650 /// [JUnit] Fails a test with no message. 00651 /// \see http://junit.sourceforge.net/javadoc/junit/framework/Assert.html#fail() 00652 #define fail( ) ADH_test_ERROR("ERROR") 00653 /// [JUnit] Fails a test with the given message. 00654 /// \see http://junit.sourceforge.net/javadoc/junit/framework/Assert.html#fail(java.lang.String) 00655 #define fail_Msg( MSG ) ADH_test_ERROR(MSG) 00656 00657 #endif // ADH_test_h 00658 00659 // EOF: ADH_test.h
1.4.1