martes, 22 de enero de 2013

TDD: Test Driven Development

Artículo perteneciente a la sección de calidad de código
Este artículo es una especificación del artículo sobre como mejorar la calidad de código

Bibliografía recomendada para este tema:


Hola a todos,

Tal vez os suene, tal vez no, pero TDD es tal vez la metodología de trabajo más importante para conseguir una buena calidad de código. Sin ella, casi nada del resto de cosas que podamos hacer las podríamos hacer, al menos no de forma segura.  Si mejorar el código fuese hacer malabares sobre la cuerda floja encima de un monociclo con un mono que fuma en pipa encima del hombro (que en muchas ocasiones es lo que  acaba siendo :D ) TDD sería los arneses y  la red de seguridad.

La teoría es muy sencilla:
1. Escribimos los test que queremos que pase nuestro software (antes de escribir ni una sola linea de código!!!)
2. Implementamos un código lo más sencillo y corto posible (KISS) que cumpla con esos tests.
3. Probamos los test.
4. Si no se cumplen los tests volvemos al punto 2 y vamos reiterando hasta conseguir un ok de los test.
5. A medida que el código se va haciendo más grande implementamos test más complejos y estrictos para verificar correctamente el conjunto del sistema.
6. De vez en cuando refactorizamos el código y pasamos los tests para asegurarnos que todo sigue funcionando.

Largo pero sencillo no? Pues bien, este ciclo de trabajo es el que permite tener de forma regular código casi automantenido , dejándonos tiempo para implementar nuevas funcionalidades en vez de perder el tiempo parcheando código antiguo.

Si buscáis en la web hay muchas artículos como este que más o menos explican lo mismo y hablan de las bondades de las diferentes herramientas que se pueden usar para implementar TDD  (killrazor hizo hace un tiempo un artículo buenísimo sobre el tema), pero he encontrado a faltar ejemplos prácticos  para que la gente lo pueda entender. Espero que el siguiente ejemplo os sea de utilidad.


Vectores.cpp

void SumaVectores(int a[4],int b[4], int c[4])
{
     int i;
   
     for(i = 0 ; i < 4 ; ++i )  
     {
           a[i] = b[i] + c[i];
     }
}

void RestaVectores(int a[4],int b[4], int c[4])
{
     int i;
   
     for(i = 0 ; i < 4 ; ++i )  
     {
           a[i] = b[i] - c[i];
     }
}

void MultiplicaVectores(int a[4],int b[4], int c[4])
{
     int i;
   
     for(i = 0 ; i < 4 ; ++i )  
     {
           a[i] = b[i] * c[i];
     }
}


Vectores.h

void SumaVectores(int a[4],int b[4], int c[4]);
void RestaVectores(int a[4],int b[4], int c[4]);
void MultiplicaVectores(int a[4],int b[4], int c[4]);



main.cpp

#include "Vectores.h"
#include <iostream>

void main(void)
{
     int a[4] = {0,1,2,3};
     int b[4] = {0,0,0,0};
     int c[4] = {0,-1,0,-2};
   
     SumaVectores(a,b,c);
     MultiplicaVectores(b,a,c);
     RestaVectores(c,b,a);
   
     std::cout <<  "Resultado:" << c[0] << " " << c[1] << " " << c[2] << " " << c[3];
     system("pause");
}

Test.cpp
#include "Vectores.h"
#include <iostream>

FILE *fp;

void TEST_SumaVectores(void)
{
     int a[4] = {0,1,2,3};
     int b[4] = {0,1,2,3};
     int c[4] = {5,6,7,8};
     
     SumaVectores(a,b,c);
     
     if(a[0] != 5 || a[1] != 7 || a[2] != 9 || a[3] != 11)
             fprintf(fp,"TEST de suma de vectores incorrecta\n");
     
}


void TEST_RestaVectores(void)
{
     int a[4] = {0,1,2,3};
     int b[4] = {1,6,2,3};
     int c[4] = {5,4,7,2};
     
     RestaVectores(a,b,c);
     
     if(a[0] != -4 || a[1] != 2 || a[2] != -5 || a[3] != 1)
             fprintf(fp,"TEST de resta de vectores incorrecta\n");
     
}

void TEST_MultiplicaVectores(void)
{
     int a[4] = {0,1,2,3};
     int b[4] = {0,1,2,3};
     int c[4] = {5,0,7,2};
     
     MultiplicaVectores(a,b,c);
     
     if(a[0] != 0 || a[1] != 0 || a[2] != 14 || a[3] != 6)
             fprintf(fp,"TEST de multiplicación de vectores incorrecta\n");

     
}

void main(void)
{
     fp = fopen("Log.txt","w");
     
     fprintf(fp,"Iniciando test básicos de vectores\n");
     TEST_SumaVectores();
     TEST_RestaVectores();
     TEST_MultiplicaVectores();
     fprintf(fp,"Fin test básicos de vectores\n");
             
     fclose(fp);
}

compiler.bat
 echo OFF

echo *********Seteando variables del sistema para Visual Studio**********************
call "c:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat"

echo *******************************Compilando***************************************
cl /EHsc /c main.cpp
cl /EHsc /c Test.cpp
cl /EHsc /c Vectores.cpp

echo ******************************Ejecutando Tests Unitarios************************
link test.obj vectores.obj
call test.exe

echo ******************************Ejecutando****************************************
link main.obj vectores.obj
call main.exe

pause


Que hace todo esto?? Bueno, basicamente compilamos todos los archivos y hacemos dos linkados, uno con la versión buena, la que nos interesa y otro linkado con una versión de test cuya única funcionalidad es asegurar que todo funciona correctamente. Si encuentra errores lo pone en un log.txt.

Podréis observar que las pruebas son muy sencillas, normalmente las pruebas serían bastante más exhaustivas y con más niveles de complejidad, pero tal como está nos permitiría poder refactorizar las funciones de cálculo e implementarlas en ensamblador por ejemplo sin demasiados riesgos para el funcionamiento global.

En próximos capítulos iremos complicando cada vez un poquito más el tema para que veáis hasta donde se puede llegar.

Espero que os haya gustado

Nos vemos


LordPakusBlog


0 comentarios :

Publicar un comentario

Entradas populares