Debe introducir al menos 3 caracteres en el buscador.
Inicio / Wikis / Tutoriales / Pruebas unitarias con CPPUnit - Desarrollo guiado por puebas

Pruebas unitarias con CPPUnit - Desarrollo guiado por puebas

 ***-- (2 opiniones)
Creative Commons Tutorial de Juan Manuel - 27 de Agosto de 2005
Temas Relacionados: Programación estructurada
6. Desarrollo guiado por puebas
Anteriormente hemos dicho que el eXtreme Programming (XP) propone un modelo de pruebas ligeramente distinto. Bien, expliquemos esto con detalle porque merece la pena.

Una de las metodologías ágiles existentes es la llamada Test Driven Development, (o TDD) es decir: desarrollo guiado por pruebas. Esta metodología, (una de las que inspiró a Kent Beck a la hora de concebir el XP) propone realizar las pruebas unitarias antes que la propia unidad.
Espera un momento... ¿cómo vamos a probar algo que todavía no existe? Es como si intentamos medir la velocidad máxima de un coche antes de que se haya fabricado el primer ejemplar. Pues aunque suene raro, y no sea posible realizar en otros ámbitos, en el mundo del desarrollo de software esto es viable, y además muy recomendable.

Esta metodología está muy pautada y hay que seguir los siguientes pasos:

  1. Pensar en la unidad o funcionalidad que queremos desarrollar, centrándonos en cómo nos gustaría que se usase desde el exterior. Una buena manera de hacer esto es imaginarnos que vamos a comprar esa unidad a una empresa y podemos definir cómo queremos usarla. El cliente siempre manda ¿no? pues imaginemos que somos los clientes y van a programarnos esa unidad a nuestro gusto.
  2. Escribir el pseudocódigo de uno o varios ejemplos de su uso más habitual. Cada uno de estos ejemplos se llama en análisis "Caso de Uso", ya que define uno de los casos en que se usará la unidad que estamos analizando. No detallaremos ni escribiremos ejemplos de usos extraños, sino los ejemplos típicos de uso. Como vamos a ser los que usemos la futura unidad, intentaremos que el uso sea lo más sencillo posible a la vez que flexible y potente. Cuando terminemos este paso, tendremos una lista de Casos de Uso, además de una lista de tareas a completar. De este modo, como dicen en mi pueblo, hemos matado dos pájaros de un tiro: hemos obtenido el análisis de casos de uso (incluso podríamos representarlo con un diagrama UML de Casos de Uso), y hemos confeccionado una lista de tareas a completar para dar por finalizada la unidad.
  3. Codificar el pseudocódigo de cada uno de los ejemplos en forma de Caso de Prueba, verificando en todo momento los retornos de los métodos que hemos definido en el paso anterior. De este modo, cada Caso de Uso tiene su correspondiente Caso de Prueba que lo verifica. Durante esta codificación refinaremos el uso que hemos imaginado, añadiendo o quitando parámetros, modificando los retornos de los métodos, etc.
  4. Compilar ese Caso de Prueba. Lógicamente, fallará la compilación, ya que se están haciendo llamadas a métodos o unidades que no existen.
  5. Codificar todas aquellas clases/funciones/métodos/lo-que-sea para que la prueba compile. Es importante que todos los métodos que codifiquemos retornen un valor de error, que dependiendo del método en cuestión puede ser false, -1, o cualquier otra cosa.
  6. Compilar otra vez el Caso de Prueba: ahora tiene que compilar correctamente ya que en el paso anterior hemos añadido todo lo necesario.
  7. Ejecutar la prueba: fallará estrepitosamente porque todos los métodos o funciones están vacíos y retornan un valor de error. Si alguna prueba pasa correctamente, significará que la prueba está mal escrita.
  8. Codificar cada una de las funciones/métodos para que todas las pruebas vayan pasando. Posiblemente no pasarán a la primera, sino que las pruebas nos irán indicando si el código que escribimos va por buen camino o no.
  9. Daremos por finalizado el ciclo cuando todas las pruebas hayan pasado. En ese momento estaremos seguros de que nuestra unidad funciona para los Casos de Uso que hemos probado.
  10. Opcionalmente podemos añadir nuevas pruebas para verificar más a fondo la unidad: añadir nuevos casos de uso más improbables (aunque posibles), pasar valores extremos a los métodos (negativos cuando se esperan positivos, cadenas vacías, punteros nulos, etc.), comprobando que la situación se controla y se retorna el error correspondiente, etc.

Si nunca habéis aplicado esta metodología, quizá estos pasos os resulten demasiado extraño o no quede muy claro cómo habría que aplicarlo a un caso real. Pongamos un ejemplo. Supongamos que nos han encargado realizar una unidad que se encargue de enviar correos electrónicos. Esa unidad irá integrada en un sistema más grande, concretamente en la parte que se encarga de enviar informes de error o sugerencias de los usuarios que están usando el programa. Aplicando la metodología TDD seguiremos los siguientes pasos:

  1. Pensar en la funcionalidad que queremos desarrollar: si lo que tenemos que desarrollar es un algo que envíe correos electrónicos, uno de los Casos de Uso será enviar un correo electrónico. Además nos han dicho que se tiene que permitir el envío de hasta un archivo adjunto, así que otro caso de uso será enviar un correo con un archivo adjunto.
  2. Escribir el pseudocódigo de uno o varios casos de uso.
    Parar enviar un correo electrónico:
Para enviar un correo electrónico es necesario conocer un servidor SMTP. Con esta función establecemos los datos del servidor SMTP a través del que enviaremos el correo EstablecerServidorEnvio(ip, puerto) Con esta llamada se enviará el correo EnviarCorreo(dirección origen, dirección destino, asunto, cuerpo) Para enviar un correo electrónico con adjuntos:
Establecemos el servidor de envío EstablecerServidorEnvio(ip, puerto) Cargamos el adjunto y los metemos en un buffer adjunto = CargarAdjunto("C:\ruta\nombre.ext"); Tenemos que añadir un nuevo parámetro para pasar el adjunto Si no queremos enviar adjuntos pasaremos NULL EnviarCorreo(origen, destino, asunto, cuerpo, adjunto);
Como veis, nos han salido varias funciones/métodos que tenemos que implementar, obteniendo así una lista de tareas. Entre las tareas a completar está la implementación de las funciones: EstablecerServidorEnvio, CargarAdjunto y EnviarCorreo.
  1. Codificar ese pseudocódigo de cada uno de los ejemplos en forma de Caso de Prueba:---Parar enviar un correo electrónico:
int ProbarEnviarCorreo() { char *ip; int puerto; char *origen, *destino, *asunto, *cuerpo;
datos del servidor ip = "127.0.0.1"; puerto = 23; si la función retorna error, no pasamos la prueba if ( !EstablecerServidorEnvio(ip, puerto) ) return (FALSE); datos del correo origen = "yo@mismo.com"; destino = "tu@mismo.com"; asunto = "un correo de prueba"; cuerpo = "texto del correo de prueba\r\nChao pescao."; el último parámetro indica que no se envía adjunto if ( !EnviarCorreo(origen, destino, asunto, cuerpo, NULL) ) return (FALSE); return (TRUE); } Para enviar un correo electrónico con adjuntos:
int ProbarEnviarCorreoConAdjunto() { char *ip; int puerto; char *origen, *destino, *asunto, *cuerpo; char *ruta; void *adjunto;
datos del servidor ip = "127.0.0.1"; puerto = 23; if ( !EstablecerServidorEnvio(ip, puerto) ) return (FALSE); datos del adjunto ruta = "C:\\fichero.ext"; adjunto = CargarAdjunto(ruta); if (adjunto
NULL) return (FALSE); datos del correo origen = "yo@mismo.com"; destino = "tu@mismo.com"; asunto = "un correo de prueba"; cuerpo = "texto del correo con adjunto\r\nChao pescao."; if ( !EnviarCorreo(origen, destino, asunto, cuerpo, adjunto) ) return (FALSE); return (TRUE); }
  1. Compilar ese Caso de Prueba. La compilación falla porque no encuentra las funciones EstablecerServidorEnvio, CargarAdjunto o EnviarCorreo.
  2. Declararemos las funciones, dejando el cuerpo vacío y que retorne error en todas ellas.
  3. Compilamos de nuevo las pruebas: ahora funcionan porque ya se encuentran las funciones.
  4. Ejecutamos las pruebas: fallarán todas porque lo único que hacen las funciones es retornar error.
  5. Codificaremos las tres funciones. Durante la codificación nos damos cuenta de algún detalle que no hemos tenido en cuenta: la función CargarAdjunto debe retornar el número de bytes que ocupa el archivo adjunto, además ese número de bytes hay que pasarlo también a la función EnviarCorreo. También necesitamos darle un nombre al fichero adjunto. Esto supone cambios en el prototipo de las funciones, así que tendremos que modificar también las pruebas. Finalmente, decidimos definir una estructura que represente el fichero adjunto, y pasaremos esta estructura a la función EnviarCorreo.
Finalmente, las prueba de envío de correo con adjunto quedará así: int ProbarEnviarCorreoConAdjunto() { char *ip; int puerto; char *origen, *destino, *asunto, *cuerpo; char *ruta; ADJUNTO adjunto; datos del servidor ip = "127.0.0.1"; puerto = 23; if ( !EstablecerServidorEnvio(ip, puerto) ) return (FALSE); datos del adjunto. Ahora se usa un struct adjunto.ruta = "C:\\fichero.ext"; adjunto.datos = NULL; se rellenará CargarAdjunto adjunto.size = ; se rellenará CargarAdjunto if ( !CargarAdjunto(&adjunto) ) return (FALSE); datos del correo origen = "yo@mismo.com"; destino = "tu@mismo.com"; asunto = "un correo de prueba"; cuerpo = "texto del correo con adjunto\r\nChao pescao."; ahora se pasa la estructura del adjunto if ( !EnviarCorreo(origen, destino, asunto, cuerpo, &adjunto) ) return (FALSE); return (TRUE); }
  1. Después de estas pequeñas correcciones, ejecutaremos las pruebas las veces que sean necesarias hasta que pasen correctamente, momento en el que daremos por terminado el ciclo.
  2. Para asegurarnos bien, verificaremos cómo se comportan las funciones antes parámetros incorrectos:
int ProbarEnviarCorreo() { char *ip int puerto; char *origen, *destino, *asunto, *cuerpo; datos del servidor ip = "127.0.0.1"; puerto = 23; datos del correo origen = "yo@mismo.com"; destino = "tu@mismo.com"; asunto = "un correo de prueba"; cuerpo = "texto del correo de prueba\r\nChao pescao."; llamar a EnviarCorreo antes de establecer el servidor Debe retornar error, así que si retorna ok, no se pasa la prueba if ( EnviarCorreo(NULL, destino, asunto, cuerpo, NULL) ) return (FALSE); dirección ip incorrecta. Si retorna Ok, no pasa la prueba. if ( EstablecerServidorEnvio(NULL, puerto) ) return (FALSE); if ( EstablecerServidorEnvio(, puerto) ) return (FALSE); // puerto incorrecto if ( EstablecerServidorEnvio(ip, -1) ) return (FALSE); if ( EstablecerServidorEnvio(ip, ) ) return (FALSE); // caso correcto if ( !EstablecerServidorEnvio(ip, puerto) ) return (FALSE); // datos del correo origen = "yo@mismo.com"; destino = "tu@mismo.com"; asunto = "un correo de prueba"; cuerpo = "texto del correo de prueba\r\nChao pescao."; // dirección origen incorrecta if ( EnviarCorreo(NULL, destino, asunto, cuerpo, NULL) ) return (FALSE); if ( EnviarCorreo("yo", destino, asunto, cuerpo, NULL) ) return (FALSE); if ( EnviarCorreo(, destino, asunto, cuerpo, NULL) ) return (FALSE); dirección destino incorrecta if ( EnviarCorreo(origen, NULL, asunto, cuerpo, NULL) ) return (FALSE); if ( EnviarCorreo(origen, "yo", asunto, cuerpo, NULL) ) return (FALSE); if ( EnviarCorreo(origen, "", asunto, cuerpo, NULL) ) return (FALSE); asunto incorrecto if ( EnviarCorreo(origen, destino, NULL, cuerpo, NULL) ) return (FALSE); cuerpo incorrecto if ( EnviarCorreo(origen, destino, asunto, NULL, NULL) ) return (FALSE); caso correcto if ( !EnviarCorreo(origen, destino, asunto, cuerpo, NULL) ) return (FALSE); return (TRUE); }

Como habéis visto, durante las propia etapa de pruebas nos hemos dado cuenta de ciertos errores de diseño. Si no hubiéramos aplicado la metodología TDD, habríamos codificado la unidad para enviar correos la primera vez, y después nos habríamos dado cuenta de que no es correcta y tendríamos que haberla codificado por segunda vez. Escribiendo las pruebas antes, hemos analizado y diseñado más detalladamente la unidad, así que en el momento de codificarla tenemos una idea mucho más clara y precisa de lo que debe hacer y cómo lo debe hacer.
Autor y licencia de 'Pruebas unitarias con CPPUnit - Desarrollo guiado por puebas'
Juan Manuel Extraído de: http://www.lawebdejm.com

Creative Commons License
Esta obra está bajo una licencia de Creative Commons.
Este contenido ha sido recopilado por el equipo de Wikilearning. Todo el contenido recopilado se ha obtenido respetando y comunicando en nuestro site la licencia de cada fuente.
Wikilearning tiene permiso expreso por escrito de los autores para publicar los contenidos que ha extraído de otras webs, incluyendo su uso comercial.

Wikis relacionados con 'Pruebas unitarias con CPPUnit - Desarrollo guiado por puebas'

La realización de las pruebas de trabajo la hace habitualmente el futuro jefe de trabajo... Más »
Las competencias son aprendidas y la persona puede desarrollarlas a través de diferentes estímulos. Las... Más »
La evaluación del impacto ambiental, en el diseño de obras y actividades de interés público... Más »
Con el propósito de facilitar a los lectores aquellos notables Autores en Comportamiento y Desarrollo... Más »
Hemos tenido que recuperar la técnica mayéutica de los grandes maestros (griegos, chinos...) de la... Más »
¿Estás seguro de que deseas eliminar este capítulo?