Teoría: Pruebas de Unidad

Introducción

En cualquir sistema complejo, es crítico probarlo praa saber que funcionará una vez que se lance en vivo. Muchos grupos de trabajo se limitan a dedicar una o dos personas a probar el sistema. Éste método tiene algunos problemas

  1. El programador está separado de la prueba. Esto impide que el programador proporcione información acerca de condiciones extremas de prueba, y el aislamiento también provoca que el programador siga cometiendo los mismos errores por no tener información acerca de como se prueba su sistema.
  2. Una prueba que se limita a utilizar el sistema como un usuario no cubre problemas de diseño de objetos. Mientras el programa crece, el código espagueti se hace más y más complejo. El problema se hace peor exponencialmente mientras el sistema se mantenga en esta situación, hasta que arreglarlo se vuelve más caro que comenzar de nuevo.
  3. Como humanos, nos es fácil olvidar maneras alternativas de utilizar las mismas funciones.
    Por ejemplo, ¿utilizas Archivo/Guardar, el boton para guardar o Control-S? ¿Si es Archivo/Guardar, con el teclado o con el mouse? ¿Còmo sabes que los dos funcionan? Todas estas condiciones parecen multiplicarse diario.

Lo que las pruebas de unidad buscan es evitar dichos problemas para que la calidad del sisterma sea mayor. Es un hecho comprobado que los sistemas que están diseñados utilizando metodologías que ponen la prueba como parte integral del diseño terminan siendo más confiables.

¿Qué es una Prueba de Unidad?

Una prueba de unidad pretende probar cada funciòn en un archivo de programa simple (una clase en terminologìa de objetos). Las librerías de pruebas de unidad formalizan este trabajo al proporcionar clases para pruebas.

La prueba de unidad ayuda a que el mòdulo se haga independiente. Esto quiere decir que un mòdulo que tiene una prueba de unidad se puede probar independientemente del resto del sistema. Una vez que un gran porcentaje de su programa cuente con pruebas de unidad,

Note que las pruebas de unidad no sustituyen a las pruebas funcionales del departamento de control de calidad, pero a la larga reducen la cantidad de errores de regresión en futuras versiones del producto.

Una buena prueba de unidad:

Advertencia Pruebas de Unidad y Diseño de Software

Las pruebas de unidad influencían el diseño (para bien). Esto quiere decir que el aplicar pruebas de unidad a un sistema previamente escrito será difícil. Cuando usted se decida a añadir pruebas de unidad a un sistema existente, asegúrese de escojer sus batallas y hacer pruebas de regresión del sistema. Si su sistema es mediano o grande, es conveniente planear sus pruebas y aplicar los cambios necesarios a traves de varias versiones futuras. No lo intente todo al mismo tiempo.

Cobertura

Otro concepto relacionado a las pruebas de unidad es el de cobertura. ¿Cómo sabemos cuantas líneas del programa están siendo probadas (y más importante, las que no se probaron)? Una vez que usted tiene pruebas de unidad, probablemente le interesará tener un reporte de las líneas que no se han probado. Una utilería gratuita para proporcionar estos reportes en ruby se llama, apropriadamente, rubycoverage. Rubycoverage no viene con rails - usted lo debe instalar utilizando gems.

Desarrollo Basado en Pruebas (o Metodología "Prueba Primero")

Mencionamos anteriormente que las pruebas de unidad influencían positivamente el diseño de su programa. Es por esto que muchas metodologías ágiles son partidarias de lo que se llama "probar primero". 

La idea del desarrollo basado en pruebas consiste en utilizar las pruebas de unidad como una pre-verificación y guía para comenzar a escribir el código. Al escribir la prueba primero (o al menos al mismo tiempo que el módulo original), a la larga es más sencillo mantener el programa y el diseño nunca se perjudica al punto que crea dificultades en el control de calidad.

La importancia de Pruebas de Unidad en Rails

En ruby on rails, y en todos los lenguajes interpretados en uso hoy día, la idea de las pruebas de unidad es central e importantísima. Como casi todos los errores en un programa interpretado sólo ocurren cuando el programa corre (porque no hay etapa de compilación), en esta clase de lenguajes es esencial escribir las pruebas de unidad al mismo tiempo que el código y asegurar una cobertura adecuada.

Las pruebas de unidad y el desarrollo basado en pruebas son importantes en todos los lenguajes, pero son aún más importantes en Ruby y Rails. No lo olvide.

Por este motivo, durante el curso veremos cómo podemos escribir nuestras pruebas primero (o al menos al mismo tiempo) que el resto del sistema.

Basado en el requerimiento, primero escribimos una prueba inicial que nos ayudaría a determinar que el requerimiento funciona correctamente en su camino feliz, o sea su camino más sencillo. Obviamente, la prueba debe fallar porque todavía no hay código de verdad.

Ahora que la prueba falla, podemos comenzar a escribir la implementación para que la prueba funcione, de la manera más sencilla como sea posible.

Una vez que tengas tu implementación inicial, podemos hechar un vistazo a los casos excepcionales. Por ejemplo, si escribimos un requerimiento que dice que los usuarios pueden subscribirse a nuestro sistema ellos mismos, y que el sistema les enviará un correo electrónico cuando se suscriban, ¿qué pasa si el usuario es menor de edad? ¿Qué pasa si el usuario escribe un correo electrónico no válido? La idea es crear suficientes pruebas para los casos diferentes típicos.

Pruebas de Unidad y Rails

Ruby on Rails utiliza la librería Test::Unit como estándar para crear pruebas de unidad. Cuando usted utiliza los generadores de Rails para crear cualquier módulo, ya sea modelos o controladores,  rails automáticamente crea una prueba de unidad para dicho controlador o modelo en el directorio test, incluyendo una que otra prueba básica. El diseño MVC de Rails hace más fácil escribir pruebas de unidad. Cuando usted extienda el programa sólo tiene que mantener las pruebas.

Además, el comando "rake" en una aplicación de rails ejecuta las pruebas. De esta manera usted puede añadir las pruebas de unidad y ejecutarlas con un sólo comando.