Modulo [B]asico para prueba [unit]aria de programas:
|
Colección de pruebas. Más...
#include <BUnit.h>
Tipos públicos | |
typedef std::list < TestCase_is_base_for_TestSuite * > | container_type |
Tipo del contenedor (escoja el que prefiera). | |
typedef container_type::iterator | iterator |
Iterador del contenedor. | |
typedef const container_type::iterator | cons_iterator |
Iterador del contenedor (const ). | |
typedef const container_type | const_container_type |
Tipo del contenedor (const ). | |
Métodos públicos | |
TestSuite (const char *name=0) | |
Constructor. | |
virtual | ~TestSuite () |
Destructor. | |
bool | addTest (TestCase &T) |
Agrega la prueba "T" a la colección "*this" (no la destruirá). | |
bool | addTest (TestCase *T) |
Agrega la prueba "*pT" a la colección "*this" (y luego la destruirá). | |
void | addSuite (TestSuite &SSS) |
Traslada todas las pruebas de la colección "SSS" y las agrega a "*this" . | |
bool | run () |
Invoca TestCase::run() para cada prueba en la colección. | |
void | runBare () |
Invoca TestCase::runBare() para cada prueba en la colección. | |
int | countTestCases () const |
Cantidad de casos de prueba. | |
int | failureCount () const |
Cantidad de pruebas que fallaron. | |
int | successCount () const |
Cantidad de pruebas exitosas. | |
void | reset () |
Elimina todas las pruebas realizadas. | |
const_container_type & | allTests () const |
Referencia al contenedor con todos los casos de prueba. | |
const std::string | toString () const |
Hilera "enooorme" que contiene copia del registro de pruebas no exitosas, separados por "\n" . | |
const std::string | summary () const |
Retorna un hilera que contiene el nombre, cantidad de éxitos y fallas. | |
const std::string | toXML () const |
Hilera XML que contiene una copia de las pruebas no exitosas. | |
bool | Run () |
Sinónimo de run() . | |
bool | runTest () |
Sinónimo de run() . | |
virtual void | setUp () |
Establece el ambiente en que se realizará la prueba. | |
virtual void | tearDown () |
Destruye el ambiente de prueba. | |
int | runCount () const |
Cantidad total de pruebas realizadas. | |
int | errorCount () const |
Siempre retorna 0 (cero): "Cantidad de errores". | |
bool | wasSuccessful () const |
Retorna "true" si todas las pruebas han sido exitosas. | |
std::string | getName () const |
Obtiene el nombre de la prueba. | |
void | setName (const char *name=0) |
Le cambia el nombre a la prueba por "name" . | |
const std::string | report () const |
Retorna la hilera encabezado summary() seguido toString() . | |
const std::string | failureString () const |
Sinónimo de toString() . | |
Métodos públicos estáticos | |
template<class T > | |
static std::string | toString (const T &val) |
Retorna una hilera std::string contruida desde el valor de val . | |
Métodos protegidos | |
void | recordSuccess () |
Registra como exitoso el resultado de una prueba. | |
void | recordFailure (const char *label, const char *fname, int lineno, bool must_copy=false) |
Registra que la prueba no tuvo éxito. | |
void | recordFailure (const std::string &label, const char *fname, int lineno) |
Registra que la prueba no tuvo éxito. | |
void | testThis (bool cond, const char *label, const char *fname, long lineno, bool must_copy=false) |
Efectúa la prueba y registra su resultado. | |
void | testThis (bool cond, const std::string &label, const char *fname, long lineno) |
Sinónimo de testThis() . | |
int | nPass () const |
Sinónimo de successCount() [OBSOLETO]. | |
int | nError () const |
Sinónimo de failureCount() [OBSOLETO]. | |
Atributos protegidos | |
int | m_pass |
Cantidad de pruebas exitosas. | |
int | m_failure |
Cantidad de pruebas que han fallado. | |
const char * | m_name |
Nombre del caso de prueba. | |
bool | m_test_suite_destroy |
Contiene "true" si la prueba está almacenada en memoria dinámica. | |
std::list< TestCaseFailure > | m_failureList |
Contenedor para almacenar las pruebas que han producido fallas. | |
Métodos privados | |
bool | iAmTestSuite () const |
Retorna true solo para la clase derivada TestSuite<> . | |
TestSuite (const TestSuite &DONTcopy) | |
Esta declaración "private" prohibe la copia de casos de prueba. | |
TestSuite & | operator= (const TestSuite &DONTcopy) |
Esta declaración "private" prohibe la copia de casos de prueba. | |
Atributos privados | |
container_type | m_allTest |
Contenedor en donde se almacenan los punteros a las pruebas. | |
Amigas | |
class | TestSuite |
Colección de pruebas. | |
template<class TestCase > | |
void | do_toXML (const TestCase *tc, std::basic_ostringstream< char > &ost) |
Le agrega a ost la hilera de todas las pruebas no exitosas de *tc en formato XML. | |
template<class TestCase > | |
void | do_toString (const TestCase *tc, std::basic_ostringstream< char > &ost) |
Le agrega a ost la hilera de todas las pruebas no exitosas de *tc . |
Colección de pruebas.
TestCase
.TestCase::run()
.TestSuite<TestCase>::runBare()
es similar a TestSuite<TestCase>::run()
, pero antes de hacer cada prueba establece el ambientede ejecución de la prueba invocando a TestCase::setUp()
y a TestCase::tearDown()
después de realizarla.setUp()
y tearDown()
para ejecutar las pruebas de la colección, cada prueba queda "aisalda" de las demás, pues para cada una se estable el ambiente de ejecución que promete la clase TestCase
."BUnit.cpp"
, de manera que para probar programas baste incluir únicamente este archivo "BUnit.h"
."BUnit.cpp"
TestSuite<>
usé como parámetro el identificador TestCase
, que también es el nombre de la clase de la que TestSuite<>
se deriva. Este doble uso del mismo identificador confunde al compilador, porque no puede deducir que el parámetro TestCase
también es el nombre de la clase base. Por eso, uso un sinónimo para nombrar a la clase base de TestSuite<>
. Escogí el identificador TestCase_is_base_for_TestSuite
porque es descriptivo y bastante largo, por lo que es muy poco probable que un programador cliente de BUnit.h
necesite usarlo.TestSuite<>
está implementada usando plantillas para evitar forzar al programador cliente de "BUnit"
a usar 2 archivos, uno de encabezado "BUnit.h"
y otro de implementación "BUnit.cpp"
. Como no hace falta usar el archivo "BUnit.cpp"
, implementar programas de prueba es muy sencillo pues al programar las pruebas solo se necesita agregar este único renglón:#include "BUnit.h"
"BUnit"
está contenida en el archivo de encabezado de "BUnit.h"
, puede ocurrir que algunas rutinas queden duplicadas en el programa objeto cuando el encabezado "BUnit.h"
es incluido en varios archivos ".cpp"
diferentes en el mismo proyecto. En estos casos, los métodos que no son "inline" quedan definidos en varios archivos y, en consecuencia, el editor de eslabonamiento ("linker") debe reportar que el mismo módulo objeto está presente en varios archivos objeto. Cuando se usan plantillas, el sistema de compilacición se encarga de manejar esta duplicación, lo que releva al programador de esta engorrosa responsabilidad. Esto explica por qué TestSuite<>
es una clase emplantillada."BUnit.cpp"
en donde estarían las definiciones de las funciones que no son "inline".BUnit.h
esté metida en un sólo archivo obliga a implementar TestSuite<>
con plantillas, lo que a también motiva el uso de TestCase
como nombre del parámetro para la plantilla TestSuite<>
.TestSuite<>
está implementada con plantillas es lograr que la responsabilidad de eliminar duplicados de métodos y funciones caiga en el sistema de compilación, pues de lo contrario sería necesario que los programadores cliente incluyan en su proyecto el archivo de implementación "BUnit.cpp"
, lo que haría más complicado el uso de BUnit
. Este truco de programación hace que sea trabajo del compilador manejar el código de implementación que de otra manera habria habido que poner dentro de un archivo de implementación "BUnit.cpp"
. template< class TestCase > typedef TestSuite< TestCase >::container_type |
template< class TestCase > typedef TestSuite< TestCase >::cons_iterator |
template< class TestCase > typedef TestSuite< TestCase >::const_container_type |
Destructor.
TestSuite<TestCase>::addTest(TestCase* T)
(puntero).TestSuite<TestCase>::addTest(TestCase& T)
(referencia). template< class TestCase > TestSuite< TestCase >::TestSuite | ( | const TestSuite< TestCase > & | DONTcopy | ) | [private] |
Esta declaración "private"
prohibe la copia de casos de prueba.
Agrega la prueba "T"
a la colección "*this"
(no la destruirá).
"T"
cuando "*this"
sea destruido."T"
es una referencia."T"
es una colección de pruebas el efecto es similar a invocar addSuite(T)
directamente. {{ // test::addTest() class MyTest : public TestCase { public: bool run() { assertTrue( 1 == 1 ); // Ok assertTrue( 1 == 2 ); // Failure !!! return wasSuccessful(); } }; // MyTest TestSuite<TestCase> SSS; MyTest thisTest, *ptr_test = new MyTest; SSS.addTest( thisTest ); // addTest(&)==> SSS.~TestSuite<>() will NOT destroy "thisTest" SSS.addTest( ptr_test ); // addTest(*)==> SSS.~TestSuite<>() WILL destroy "ptr_test" assertTrue( 0 == SSS.failureCount() ); SSS.run(); assertTrue( 1+1 == SSS.failureCount() ); assertTrue( "" != SSS.toXML() ); TestSuite<TestCase> TTT, RRR; TTT.addTest( & SSS ); // similar to TTT.addSuite( SSS ) assertTrue( "" == SSS.toXML() ); assertTrue( "" != TTT.toXML() ); RRR.addTest( TTT ); // similar to RRR.addSuite( TTT ) assertTrue( 0 == SSS.countTestCases() ); assertTrue( 0 == TTT.countTestCases() ); // SSS y TTT become "empty" assertTrue( 2 == RRR.countTestCases() ); assertTrue( 2 == RRR.failureCount() ); // RRR has it all assertTrue( "" != RRR.toXML() ); }}
Agrega la prueba "*pT"
a la colección "*this"
(y luego la destruirá).
(pT == 0)
no agrega nada y retorna "false"
."*pT"
cuando "*this"
sea destruido."pT"
es un puntero."pT"
es una colección de pruebas el efecto es similar a invocar addSuite(*pT)
directamente. {{ // test::addTest() class MyTest : public TestCase { public: bool run() { assertTrue( 1 == 1 ); // Ok assertTrue( 1 == 2 ); // Failure !!! return wasSuccessful(); } }; // MyTest TestSuite<TestCase> SSS; MyTest thisTest, *ptr_test = new MyTest; SSS.addTest( thisTest ); // addTest(&)==> SSS.~TestSuite<>() will NOT destroy "thisTest" SSS.addTest( ptr_test ); // addTest(*)==> SSS.~TestSuite<>() WILL destroy "ptr_test" assertTrue( 0 == SSS.failureCount() ); SSS.run(); assertTrue( 1+1 == SSS.failureCount() ); assertTrue( "" != SSS.toXML() ); TestSuite<TestCase> TTT, RRR; TTT.addTest( & SSS ); // similar to TTT.addSuite( SSS ) assertTrue( "" == SSS.toXML() ); assertTrue( "" != TTT.toXML() ); RRR.addTest( TTT ); // similar to RRR.addSuite( TTT ) assertTrue( 0 == SSS.countTestCases() ); assertTrue( 0 == TTT.countTestCases() ); // SSS y TTT become "empty" assertTrue( 2 == RRR.countTestCases() ); assertTrue( 2 == RRR.failureCount() ); // RRR has it all assertTrue( "" != RRR.toXML() ); }}
void TestSuite< TestCase >::addSuite | ( | TestSuite< TestCase > & | SSS | ) | [inline] |
Traslada todas las pruebas de la colección "SSS"
y las agrega a "*this"
.
"SSS"
vacía.SSS
para evitar los problemas que surgen cuando tanto "SSS"
como "*this"
tratan de destruir la misma prueba.Invoca TestCase::run()
para cada prueba en la colección.
TestCase::setUp()
y TestCase::tearDown()
cuando ejecuta cada prueba.TestSuite<TestCase>::reset()
antes de cada prueba."true"
cuando todas las pruebas han tenido éxito (inclusive aquellas que fueron corridas antes de la invocación actual). Implementa TestCase.
Invoca TestCase::runBare()
para cada prueba en la colección.
TestSuite<TestCase>::reset()
antes de hacer cada prueba.TestCase::setUp()
antes de cada pruebaTestCase::tearDown()
después de cada prueba. {{ // test::run() class MyTest : public TestCase { int m_val; public: MyTest() : m_val(0) {} // init: m_val == 0; void setUp() { m_val = 1; } void tearDown() { m_val = 2; } bool run() { assertTrue( m_val == 1 ); return wasSuccessful(); } }; // MyTest TestSuite<TestCase> SSS; SSS.addTest( new MyTest ); SSS.addTest( new MyTest ); assertTrue( 2 == SSS.countTestCases() ); assertTrue( "" == SSS.failureString() ); SSS.runBare(); // Ok ==> setUp() sets [m_val == 1] assertTrue( "" == SSS.toXML() ); SSS.run(); // Failure: [m_val == 2] ==> value set by tearDown() std::string sssXML = SSS.toXML(); assertTrue( "" != sssXML ); // SSS contains failures. assertTrue( sssXML.find("m_val") != string::npos ); assertTrue( SSS.runCount() == 2+2 ); }}
Reimplementado de TestCase.
template< class TestCase > int TestSuite< TestCase >::countTestCases | ( | ) | const [inline] |
int TestSuite< TestCase >::failureCount | ( | ) | const [virtual] |
int TestSuite< TestCase >::successCount | ( | ) | const [virtual] |
template< class TestCase > bool TestSuite< TestCase >::iAmTestSuite | ( | ) | const [inline, private, virtual] |
template< class TestCase > TestSuite< TestCase >::TestSuite & TestSuite< TestCase >::operator= | ( | const TestSuite< TestCase > & | DONTcopy | ) | [private] |
Esta declaración "private"
prohibe la copia de casos de prueba.
bool TestCase::Run | ( | ) | [inline, inherited] |
bool TestCase::runTest | ( | ) | [inline, inherited] |
void TestCase::setUp | ( | ) | [inline, virtual, inherited] |
Establece el ambiente en que se realizará la prueba.
TestCase::run()
es un método abstracto, para facilitar la programación lo usual es que el programador no incluya invocaciones a TestCase::setUp()
y TestCase::tearDown()
pues es más fácil dejar que lo haga TestSuite<TestCase>::runBare()
.TestCase::runBare()
, el método TestCase::run()
no establece el ambiente de prueba porque no invoca ni a TestCase::setUp()
antes de la prueba ni a TestCase::tearDown()
después de la prueba.TestSuite<TestCase>::runBare()
invoca los métodos TestCase::setUp()
y TestCase::tearDown()
cuando ejecuta cada prueba.TestSuite
para ejecutarlas con TestSuite<TestCase>::runBare()
. Reimplementado en test_rational< INT >, ADH::test_Graph y test1.
void TestCase::tearDown | ( | ) | [inline, virtual, inherited] |
int TestCase::runCount | ( | ) | const [inline, inherited] |
Cantidad total de pruebas realizadas.
successCount()+failureCount()+errorCount()
. int TestCase::errorCount | ( | ) | const [inline, inherited] |
Siempre retorna 0
(cero): "Cantidad de errores".
bool TestCase::wasSuccessful | ( | ) | const [inline, inherited] |
Retorna "true"
si todas las pruebas han sido exitosas.
(successCount() == runCount())
std::string TestCase::getName | ( | ) | const [inline, inherited] |
void TestCase::setName | ( | const char * | name = 0 | ) | [inline, inherited] |
Le cambia el nombre a la prueba por "name"
.
"name"
es una hilera o puntero nulo, después usa typeid(*this).name()
para obtener el nombre de la prueba. {{ // test::setName() class MyTest : public TestCase { public: bool run() { assertTrue( 2 == 2 ); return wasSuccessful(); } }; // MyTest MyTest thisTest; assertTrue( "chorlito" != thisTest.getName() ); thisTest.setName( "chorlito" ); assertTrue( "chorlito" == thisTest.getName() ); { // thisTest.setName( std::string("chorlito") ); // won´t compile thisTest.setName( std::string("chorlito").c_str() ); // bad practice std::string V("boom!"); assertTrue( 0==strcmp( V.c_str() , "boom!") ); assertTrue( "chorlito" != thisTest.getName() ); // c_str() uses assertTrue( "boom!" == thisTest.getName() ); // static data } }}
std::string TestCase::toString | ( | const T & | val | ) | [static, inherited] |
Retorna una hilera std::string
contruida desde el valor de val
.
toString()
with standard C++ const std::string TestCase::report | ( | ) | const [inline, inherited] |
Retorna la hilera encabezado summary()
seguido toString()
.
const std::string TestCase::failureString | ( | ) | const [inline, inherited] |
Sinónimo de toString()
.
void TestCase::recordSuccess | ( | ) | [inline, protected, inherited] |
void TestCase::recordFailure | ( | const char * | label, |
const char * | fname, | ||
int | lineno, | ||
bool | must_copy = false |
||
) | [inline, protected, inherited] |
Registra que la prueba no tuvo éxito.
"fname"
y "lineno"
indican el archivo y el renglón en donde se ejecuta la prueba."fname"
y "lineno"
se obtienen invocando las macros globales "__FILE__"
y "__LINE__"
."must_copy"
indica que es necesario hacer una copia de la hilera "label"
en memoria dinámica. Este memoria dinámica será destruida cuando el caso de prueba sea destruido o cuando el método TestCase::reset()
sea invocado."label"
es una constante generada por el preprocesador al usar la macro #cond
; como esta hilera constante no está almacenada en la memoria dinámica no debe ser destruida.Este método es invocado usando la macro BUnit_FAILURE()
.
void TestCase::recordFailure | ( | const std::string & | label, |
const char * | fname, | ||
int | lineno | ||
) | [inline, protected, inherited] |
void TestCase::testThis | ( | bool | cond, |
const char * | label, | ||
const char * | fname, | ||
long | lineno, | ||
bool | must_copy = false |
||
) | [inline, protected, inherited] |
Efectúa la prueba y registra su resultado.
successCount()
.toString()
ese hecho."cond"
."fname"
y "lineno"
indican el archivo y el renglón en donde se ejecuta la prueba."fname"
y "lineno"
se obtienen con las macros globales "__FILE__"
y "__LINE__"
."must_copy"
indica que es necesario hacer una copia de la hilera "label"
, copia que será destruida cuando el registro de pruebas no exitosas sea borrado."label"
es una constante generada por el preprocesador al usar la macro #cond
y por eso su memoria no debe ser retornada. Este método es invocado usando la macro BUnit_TEST()
. {{ // test::testThis() class MyTest : public TestCase { public: bool run() { bool dont_copy = false; testThis( 2 == 2, "2 is 2", __FILE__, __LINE__, dont_copy ); // Ok testThis( 1 == 2, "1 is 2", __FILE__, __LINE__, dont_copy ); // failure #1 testThis( 2 == 1, "2 is 1", __FILE__, __LINE__, dont_copy ); // failure #2 return wasSuccessful(); } }; // MyTest MyTest thisTest; assertTrue( thisTest.wasSuccessful() ); // run() has not been executed thisTest.run(); // 2 failures assertTrue( thisTest.failureCount() == 2 ); assertTrue( ! thisTest.wasSuccessful() ); }}
void TestCase::testThis | ( | bool | cond, |
const std::string & | label, | ||
const char * | fname, | ||
long | lineno | ||
) | [inline, protected, inherited] |
Sinónimo de testThis()
.
int TestCase::nPass | ( | ) | const [inline, protected, inherited] |
int TestCase::nError | ( | ) | const [inline, protected, inherited] |
friend class TestSuite [friend, inherited] |
void do_toString | ( | const TestCase * | tc, |
std::basic_ostringstream< char > & | ost | ||
) | [friend, inherited] |
template< class TestCase > container_type TestSuite< TestCase >::m_allTest [private] |
int TestCase::m_pass [protected, inherited] |
int TestCase::m_failure [protected, inherited] |
const char * TestCase::m_name [protected, inherited] |
bool TestCase::m_test_suite_destroy [protected, inherited] |
std::list< TestCaseFailure > TestCase::m_failureList [protected, inherited] |