Una vez que hemos compilado el framework, tenemos que crear un nuevo proyecto desde C++Builder (File – New – Application) y eliminar el formulario principal que se incluye en la aplicación (Project - Remove from Project - Unit1.cpp). Después crearemos una nueva unidad (con sus archivos .cpp y .h) para codificar en ella los casos de pruebas.
Siguiendo con nuestro ejemplo, crearemos los archivos “DatosDiscoTest.h” y “DatosDiscoTest.cpp” para codificar los casos de prueba. Estos casos de prueba se van a encargar de probar todo lo relacionado con la lectura y grabación del dato, dentro de la clase “DatosDisco”. En el archivo de cabecera “DatosDiscoTest.h” codificaremos la definición de clase que podéis ver en el siguiente listado:
<code>
#if !defined(_DATOS_DISCO_TEST_H_)
#define _DATOS_DISCO_TEST_H_
#include "TestCase.h"
#include "TestCaller.h"
#include "DatosDisco.h"
class DatosDiscoTest : public TestCase
{
public:
DatosDiscoTest(std::string name);
virtual ~DatosDiscoTest();
void setUp();
void tearDown();
static Test *suite();
protected:
void testLeer();
void testGuardar();
private:
DatosDisco *fixture;
};
typedef TestCaller DatosDiscoTestCaller;
#endif
</code>
Dentro de la clase “DatosDiscoTest”, los métodos “setUp” y “tearDown” vienen heredados de la clase “TestCase”. El método “setUp” se llama automáticamente cuando iniciamos cada uno de los casos de prueba, y en este punto podemos inicializar cualquier recurso que necesitemos para hacer las pruebas. Por ejemplo, si nuestras pruebas tienen que ver con una base de datos, este suele ser el momento de realizar la conexión. El método “tearDown” es el complementario, y se ejecuta automáticamente cuando el caso de pruebas ha terminado.
El método estático “suite” retornará un nuevo objeto de tipo “Test” que representa a la colección de pruebas. Como la clase “Test” es una clase base, en realidad podremos retornar una instancia de cualquiera de sus hijos:
- TestSuite: un conjunto de casos de prueba, es decir: una colección de pruebas.
- TestCase: una prueba individual.
En la sección protected aparecen los métodos que implementan los casos de prueba. En nuestro caso tenemos dos métodos y cada uno de ellos ejecuta un único caso de prueba. Así, en el método “suite” que hemos visto antes, debemos indicar que nuestra colección de pruebas se compone de dos casos de pruebas: “testLeer” y “testGuardar”.
Por último, en la sección private tenemos un atributo con el objeto que vamos a probar. A este atributo se le conoce como fixture y se trata del objeto “sufridor” de nuestras pruebas. En el método “setUp” crearemos la instancia, asignándola a este atributo, y en el método “tearDown” la liberaremos. De este modo conseguimos tener un objeto “fresco”, recién creado, para cada una de nuestras pruebas. Si quieres saber porqué se diseñó CPPUnit de esta forma, puedes consultar
esta entrada en el blog de Martin Fowler.
La implementación de la clase es que podéis ver a continuación:
<code>
#include "DatosDiscoTest.h"
DatosDiscoTest::DatosDiscoTest(std::string name)
: TestCase(name)
{
fixture = NULL;
}
DatosDiscoTest::~DatosDiscoTest()
{
}
void DatosDiscoTest::setUp()
{
fixture = new DatosDisco();
}
void DatosDiscoTest::tearDown()
{
if (fixture != NULL)
{
delete fixture;
fixture = NULL;
}
}
Test* DatosDiscoTest::suite()
{
TestSuite *suite;
suite = new TestSuite("DatosDisco");
suite->addTest( new DatosDiscoTestCaller("Leer",
&DatosDiscoTest::testLeer) );
suite->addTest( new DatosDiscoTestCaller("Guardar",
&DatosDiscoTest::testGuardar) );
return (suite);
}
void DatosDiscoTest::testLeer()
{
ejecución de las pruebas para leer
}
void DatosDiscoTest::testGuardar()
{
ejecución de las pruebas para guardar
}
</code>
La implementación es sencilla, al menos por ahora: en los métodos “setUp” y “tearDown” se crea y destruye el objeto de pruebas (fixture), para asegurarnos que está recién creado cada vez que ejecutemos la colección de pruebas, y en el método “suite” se crea un objeto “TestSuite” y se le añaden los casos pruebas que conformen esa colección, a través de la llamada al método “addTest”.