jueves, 10 de octubre de 2013

Test Unitarios










Test Unitarios
Historias de usuarios de arquitectura de software







INTEGRANTES:
ALEXIS MIRANDA
ALVARO PINILLA
EDUARDO LOPEZ

CURSO:
GESTION DE CALIDAD DE SOFTWARE

PROFESOR:
ERWIN FISCHER

OCTUBRE 2013


Contenido



Introducción.


Para la siguiente actividad, como grupo, analizamos una historia de usuario, en nuestro caso en particular la de ingreso al sistema, la que fue realizada por los alumnos del curso de Arquitectura de Software.
A la historia de usuario seleccionada se le realizaron las pruebas correspondientes para verificar si estas estaba bien diseñada y si cumplía con su funcionalidad.
Cabe destacar que para este trabajo solo contábamos con la base de la aplicación, como lo es la historia de usuario, por lo que para realizar los test de manera efectiva fue necesario programar la futura “aplicación” de una forma sencilla pero lo suficientemente completa como para efectuarle los test.






Concepto de prueba unitaria.


En programación, una prueba unitaria es una forma de probar el correcto funcionamiento de un módulo de código. Esto sirve para asegurar que cada una de las partes que integran nuestra aplicación funcione correctamente por separado.
Las ventajas de las pruebas unitarias frente otras formas de test son el que pueden aplicarse de una forma automatizada con antelación a la puesta en producción de un código. Esto quiere decir que no es necesario el reproducir de forma manual todo el flujo necesario que lleva a la obtención del dato a verificar sino que en su lugar, delegamos esa tarea a nuestro framework de pruebas. Una ventaja añadida para los desarrolladores web es que pueden reproducir las baterías de test en cada uno de los diferentes navegadores de una forma casi desatendida. En caso de encontrarse un problema, como las pruebas se ejecutan aisladas, llegar al error resulta más sencillo. Una vez reparado, se vuelven a ejecutar los tests para comprobar la integridad en el resto de la aplicación.
En cuanto a la calidad de nuestro código, Javascript es un lenguaje muy apto para la refactorización. Al tratarse de un contenido que tiene que ser previamente descargado en cliente y ejecutado sobre una amplia variedad de plataformas, es imprescindible alcanzar el mayor rendimiento con el menor número de líneas posible. Para esta etapa en el desarrollo, contar con una batería consistente de test puede resultar de gran ayuda. Tras cada pequeña modificación del código durante la refactorización, es muy recomendable lanzar los tests para comprobar que se mantienen las funcionalidades esperadas.



¿Qué es y porque usar pruebas unitarias?


Las pruebas unitarias son test en donde cada parte (modulo, clase, función) del programa es testeado por separado. Idealmente, se pone a prueba todas las funciones y todos los casos posibles para cada una de ellas.
La prueba unitaria tiene varias ventajas:
a)       Permite probar que el programa funciona correctamente. En Python, los tests también permiten identificar variables que no existen o tipos esperados en las funciones (en otros lenguajes eso se hace en tiempo de compilación).
b)       Permite identificar en caso de que se haga una modificación que sigan funcionando correctamente todas las parte del programa. Tanto las cosas modificadas como las cosas que dependen de las modificadas. Esto es muy importante cuando se trabaja en grupo (con algún sistema de control de versiones) ya que permite asegurar que el código que usa el resto del grupo y que uno modifico sigue funcionando.
c)       Permiten documentar el código. Esto no es en forma directa, pero como los tests indican como es que se tiene que comportar el programa, viendo los tests uno puede fijarse cuál es el resultado esperado para ciertas entradas del programa. Esto no excluye que se tenga que escribir la documentación del código.
¿Entonces por qué existen bugs si se podría escribir tests? Las pruebas unitarias tienen algunas desventajas:
a)       Toman bastante tiempo de escribir. Algunas clases son fáciles de testear pero otras no tanto.
b)       Cuando se hace un gran cambio en el código (un refactor) hay que actualizar los tests. Cuando se hace un cambio que es chico, seguramente también haya que escribir o cambiar algún test pero generalmente no toma mucho tiempo.
Algo muy importante a tener en cuenta es que aprobar los tests no significa que el sistema funcione a la perfección. Un ejemplo de esto es CPython (el python que generalmente uno instala). Tiene muchísimos tests, y aun así también tiene errores. Sin embargo, los tests unitarios garantizan cierta funcionalidad mínima.





¿Cómo tienen que ser las pruebas?


Es muy importante que un test cumpla las siguientes reglas:
a)       Tiene que poder correr sin interacción humana. Es decir, los tests no deben pedir que el usuario ingrese valores en ningún caso. Para esto, es en el test mismo cuando se pasan los valores a la función.
b)       Tienen que poder verificar el resultado de la ejecución sin interacción humana. De nuevo, para saber si está bien o no el resultado no tiene que pedirle al usuario que verifique el resultado. Para esto, se tiene que saber de antemano el resultado del test con los valores que se pasaron.
c)       Un test tiene que ser independiente del otro. Es decir, el resultado de un test no debería depender del resultado anterior.
Sabiendo estas reglas, vemos que condiciones deberían comprobar los tests:
a)       Que funcione correctamente cuando los valore de entrada son válidos.
b)       Que falle cuando los valores de entrada son inválidos, o que tire una excepción.
Dentro de lo posible los tests se deberían empezar al escribir el código, ya que esto permite:
a)       Identificar detalladamente que es lo que tiene que cumplir el código a escribir.
b)       Cuando uno escribe la implementación que pasa todos los tests entonces terminó. Esto tiene dos ventajas:
o    Permite saber cuándo uno tiene que terminar de escribir el código
o    Hace que uno no tenga que escribir cosas de más.


Historia de usuario.


1) Nombre:
Ingreso al Sistema
2) Descripción:
Como usuario validado quiero poder ingresar al sistema para poder gestionar mis objetivos profesionales para obtener experiencias, mayor reputación y aumentar mi ranking.
3) Criterios de aceptación:
Cuando ingreso mis datos, para entrar al sistema este debe verificar que mi usuario es válido y no esta logeado de manera simultánea, en caso de ello debe mostrar una alerta.

Evaluación de la historia de usuario.


La historia de usuario que seleccionamos para nuestro trabajo se encuentra bien redactada, es simple de entender su funcionalidad y cumple con todo lo requerido para realizar nuestras pruebas unitarias. Por lo tanto, no es necesario efectuarle ningún tipo de cambio, con la información que se nos entrega en esta es suficiente.





Tecnologías utilizadas.


Para este trabajo utilizamos la herramienta Selenium Webdriver en conjunto con el framework UnitTest de Phyton.

1) Selenium Webdriver:
Selenium WebDriver es el sucesor de Selenium RC.
Selenium webdriver es una API que forma parte de selenium 2.0.WebDriver está diseñado para proporcionar una interfaz de programación más simple y más concisa, además de abordar algunas limitaciones en la API de SeleniumRC.
Selenium WebDriver fue desarrollado para apoyar mejor las páginas web dinámicas donde los elementos de una página pueden cambiar sin que la propia página se vuelva a cargar.
 El objetivo de WebDriver es proporcionar una API orientada a objetos bien diseñado que proporciona soporte mejorado para los problemas de avanzados de pruebas.
A la fecha (marzo de 2013) Selenium-WebDriver está completamente implementado y soportado en Java, Ruby, Python y C#.

2) Framework UnitTest de Phyton:
Las pruebas unitarias son pruebas automatizadas que prueban pequeñas piezas de código, usualmente una función o un método.

Python tiene el API de PyUnit para pruebas unitarias. El módulo se llama unittest, se basa en el framework XUnit diseñado por Ken Beck y Erich Gamma.


Análisis.


Para el desarrollo de nuestras pruebas unitarias fue necesario el crear un formulario en HTML5 y CS3 para poder efectuar las pruebas sobre este. Se debe tener en cuenta que este es un formulario de ejemplo y no representa lo que se desarrollara en el curso de Arquitectura de Software.
El código para esto quedaría de la siguiente forma:


En las siguientes imágenes se puede observar la creación de los test funcionales por parte del usuario, mezclados con test unitarios, utilizando las herramientas mencionadas anteriormente (Selenium Webdriver y Phyton).
Generamos el siguiente código:

                                                          



Y para crear las funciones que van a validar los errores que se puedan encontrar en el formulario. Estos son validadores en JavaScript:






Finalmente podemos observar lo que se muestra en el formulario al dejar un campo vacío y verificar la prueba:




Conclusión.


Pudimos ver que existen varias herramientas y/o tecnologías con las cuales se pueden efectuar pruebas a nuestras aplicaciones que nos encontramos desarrollando. Dependiendo de la naturaleza del software en proceso y a que parte de este se le realizara la prueba se puede optar por alguna herramienta en particular, en nuestro caso solo utilizamos Selenium Webdriver con el framework de Python.
Se debe tener en cuenta que se le puede realizar más de un test a esta Historia de Usuario que se analizó, pero que para efectos prácticos se le realizaron solo las que se mostraron en el informe, ya que para el objetivo final no eran necesaria más.
El ejecutar las pruebas al código, a medida que se va desarrollando la aplicación, es una técnica que puede resultar muy ventajosa para los desarrolladores y para la calidad en la entrega final del producto. Es algo que debemos tener en cuenta el día de mañana cuando nos encontremos desarrollando nuestros propios proyectos.

No hay comentarios:

Publicar un comentario