Вы находитесь на странице: 1из 8

Test Driven Design Diseo Basado en Test

Tipos de Test

Test de Aceptacin (BDD)


Test de requisitos funcionales (historias de usuario) y no funcionales (rendimiento, fiabilidad, carga, stress, diseo, etc) . En general este grupo de test, son los que le interesan al Dueo de Producto, ya que son los que le garantizan la calidad del software sin entrar en detalles tcnicos o de implementacin. Cuando el diseo del sistema se inicia tomando en cuenta las especificaciones del Dueo de Producto, y se hacen test automatizados para ello, se dice que se est realizando BDD (Behavior Driven Design Diseo basado en comportamiento).

Funcional
Son Test de Aceptacin referidos a funcionalidades, abarcan una historia de usuario.

Sistema
Son pruebas tcnicas automatizadas que van de extremo a extremo de los bordes del sistema, por ejemplo de la interfaz grfica a la base de datos, correos u otros sistemas externos. Ejemplo capas del sistema: Propia GUI / WEB (HTML/TWIG/Css/Javascript) Terceros Browser

Lgica Negocio (PHP, etc.) Symfony / Doctrine

Base de Datos (Estructura y datos) (Tablas-Registros) MySQL

Un test de sistema, simula que se realiza una accin o entrada en la GUI, y luego comprueba si lo guardado en la base de datos es lo esperado. Si tiene que enviar un email o hacer una llamada a otro sistema, es algo que tambin puede ser comprobado. Como pueden ser lentas y frgiles (pequeos cambios en el sistema pueden romperlo) y requerir mucho mantenimiento, si ya los componentes son testeados con test unitarios o de integracin, no hace falta volverlos a tener bajo prueba en un test de sistema. Por su lentitud se suele delegar al sistema de integracin continua para que los ejecute una vez al da, normalmente a la noche (nightly build). Tambin son llamados Smoke Test (http://www.softqanetwork.com/importancia-de-los-smoke-test). Solo hacen test de sistemas sobre los componentes o capas cuya responsabilidad de desarrollo es propia. Se confa que los de terceros estn suficientemente probados.

Integracin
Son test que comprueban que la interaccin entre distintos componentes se realiza correctamente. De cierta forma abarca a los test de sistema, pero no necesariamente tienen que ir de extremo a extremo. En el ejemplo anterior, probando que la GUI llama correctamente a la lgica de negocio, sin comprobar la base de datos, sera un test de integracin. O si probamos la lgica de negocio, sin tocar la GUI, y comprobamos que se guardan bien los resultados en la base de datos, sera tambin un test de integracin, sin llegar a ser un test de sistema.

Unitario
Son test que se realizan para comprobar que UN componente cumple su tarea. Se suelen implementar test solo para los mtodos pblicos, ya que son las llamadas que va a recibir el objeto desde su exterior. Si un mtodo pblico tiene varios posibles caminos internamente, deben escribirse varios test para ese mismo mtodo, un test para cada camino. Los mtodos protegidos o privados, sern probados con el test del mtodo pblico que pase por el

camino que contempla la llamada a esos mtodos protegidos o privados. Si no hay camino posible para llamar al mtodo protegido o privado, entonces es cdigo muerto que debera ser eliminado. Se puede escribir test unitario para un mtodo protegido o privado, cuando se quiere aislar y corregir un error (ver seccin Correccin de Incidencias). Con el fin de tener un test ms rpido y que asle esa incidencia. En definitiva para realmente ser unitario, debe cumplir con las siguientes caractersticas:

Caractersticas Test Unitarios


Un Test Unitario debe ser FIRST Fast - Rpido Independent - Independiente Repeteable - Repetible Small - Pequeo Transparent - Transparente
Rpido:

Debe ejecutarse en fracciones de segundo.


Independiente:

No dependa y no afecte otros test. Es decir, se debe evitar el xito de un test dependa que otro test se ejecute previamente y correctamente. Tambin es importante que tampoco se dependa de otro componentes del sistema. Por ejemplo si queremos probar un objeto que realiza ventas y usa otros objetos para el clculo de impuestos y el cobro de la tarjeta de crdito. Estas dependencias deben ser simuladas (mock, stubs, etc), y esos otros objetos deben tener sus propios test unitarios. Es importante porque si hay una falla, resultar ms difcil identificar donde se encuentra la falla. En cambio si el test es realmente independiente, se sabr con certeza que el problema es realmente del componente bajo prueba. Si se viola este principio, desde el punto de vista de la dependencia con otros componentes, deja de ser un Test Unitario, y se convierte en un Test de Integracin. Hay autores, que permiten una excepcin a esta regla, y es cuando el otro componente, no tiene lgica de negocio (ej. objeto de entidad), o es una librera desarrollada por un tercero y que confiamos en su fiabilidad (ej. componentes de Symfony, funciones nativas de php, etc.).
Pequeo - Atmico

Cada test debe probar un solo comportamiento, es decir, un solo camino. Por tanto si dependiendo de los parmetros, del estado del objeto (variables de campo), o de las condiciones del sistema, puede variar el recorrido, entonces hay que hacer un test para cada uno de los posibles caminos o estados.

Por ejemplo, dada la funcin:


functionsaludo(sexo,nombre){ salida=''; if(sexo='M'){ salida=HolaSr..nombre; }elseif(sexo='F'){ salida=HolaSra..nombre; } }

No se puede tener este test:


functiontestSaludo(){ salida=saludo('F','Cesar'); Assert.isEquals(salida,HolaSra.Cesar); salida=saludo('M','Cesar'); Assert.isEquals(salida,HolaSr.Cesar); }

Lo correcto es tener un test para cada camino:


functiontestSaludo_sexo_F(){ salida=saludo('F','Cesar'); Assert.isEquals(salida,HolaSra.Cesar); } functiontestSaludo_sexo_M(){ salida=saludo('F','Cesar'); Assert.isEquals(salida,HolaSr.Cesar); }

Incluso, hay unos caminos no contemplados:


functiontestSaludo_sexo_Vacio(){ salida=saludo('','Cesar'); Assert.isEquals(salida,); } functiontestSaludo_sexo_Cualquier_Cosa_pero_no_M_F(){ salida=saludo('asdasdasd','Cesar'); Assert.isEquals(salida,); }

Repetible - Inocuo

Debe ser igual, ejecutar un test, 1, 20 o 100 veces. Y debe poder ejecutarse en cualquier entorno. Es por ello que un test unitario, debe tratar que sus resultados no alteren el estado del sistema. Un test unitario no debe depender de una configuracin local (por ejemplo que el test solo funcione en el equipo del autor, y no funcione en el de otros desarrolladores o en el servidor de integracin continua). Se puede permitir que un test, toque la base de datos, o guarda sus resultados en disco, es decir, que afecte el estado de forma persistente, si esto no afecta a otros test o futuras ejecuciones del mismo test. Por ejemplo se borra la base de datos o el fichero antes de la ejecucin del test.

Esto ltimo viola un poco la caracterstica de independencia, pero es la excepcin mencionada cuando se trata de un componente de un tercero en el que se confa.
Transparente

Debe comunicar perfectamente la intencin del autor . Se recomienda que el nombre del test, debe identificar lo que se est probando y bajo que parmetros o condiciones. Y la organizacin interna, la lectura del cdigo, sus variables, deben ser legibles y entendibles por cualquier otro desarrollador. En fin debe quedar claro, lo que se est probando, bajo que condiciones, y el resultado esperado.

Partes de un Test
Indistintamente de su tipo, un test implementado con un framework xUnit, suele estar dividido en las siguientes partes. AAA (Arrange, Act, Assert) PAA (Preparar, Actuar, Afirmar)

Arrange - Preparar:
Inicializar SUT (objeto / componente a probar). Inicializar variables de parmetros. Preparar dobles (mocks o stubs) de otros componentes. Dejar el sistema en el estado inicial esperado (base de datos con registros a consultar, fichero de prueba a abrir, etc).

Act - Actuar:
Ejecutar tarea / mtodo del SUT (Subject under test - Sujeto bajo prueba)

Assert - Afirmar:
Comprobar si los resultados son los esperados. Realizar las llamadas a los mtodos assert, para comprobar si los resultados, el estado final, es como se espera. Ejemplo: functionsaludoTest_sexo_M(){ //Arrange sexo='F'; nombre='Cesar'; //Act salida=saludo(sexo,nombre); //Assert Assert.isEquals(salida,HolaSr.Cesar); }

Otros conceptos:
Caso de Prueba (TestCase): En los frameworks xUnit, se se agrupan los test en Casos de Prueba, suelen ser una clase si se trata

de un lenguaje orientado a objetos. A nivel de los test unitarios, se suele implementar una clase de Caso de Prueba por cada clase o componente. Suite de Pruebas: Los frameworks xUnit, suelen permitir definir suites de pruebas, que abarcan varios Casos de Prueba o incluso otros Suites de Pruebas. Resultan especialmente tiles cuando no queremos ejecutar todas las pruebas, sino solo un conjunto de ellas. Por ejemplo mientras hacemos un desarrollo, hacemos una suite de pruebas que solo contemple las pruebas de las clases o componentes que estn modificndose. De cualquier manera, se recomienda ejecutar todos los test antes de compartir el cdigo con el resto del equipo de desarrollo. A menos que probar todo el sistema sea muy lento (ms de 20 o 30 minutos), caso en el que solo probamos las clases que pensamos que pudimos haber afectado, y se delega al Sistema de Integracin Continua la ejecucin de las pruebas sobre todo el sistema. Es por ello que para evitar esta situacin, se debe tratar que los test unitarios y la mayora de los test de integracin sean rpidos.

Implementacin de un Test PHPUnit


Para test Unitarios se extiende de \PHPUnit_Framework_TestCase , que un proporciona framework con setUp, tearDown, assert, etc. Para test Funcionales se extiende de Symfony\Bundle\FrameworkBundle\Test\WebTestCase que a su vez hereda de PHPUnit_Framework_TestCase,WebTestCaseproporciona la posibilidad de obtener un cliente web y una instancia del kernel symfony. El mtodo setUp, se suele utilizar para inicializaciones que se necesiten en comn entre varios test del caso de prueba. Por ejemplo, inicializar la conexin con base de datos, limpiarla y dejar los registros iniciales. El mtodo tearDown, para finalizaciones en comn de varios test del caso de prueba. Por ejemplo, limpiar la base de datos, cerrar la conexin con la base de datos, etc. PHPUnit proporciona varios mtodos de Assert, para las comprobaciones luego de la accin a probar. Como assertEquals, assertTrue, assertFalse, assertNull, assertNotNull, etc. (ver manual de phpunit http://www.phpunit.de/manual/3.6/en/writing-tests-for-phpunit.html#writing-tests-forphpunit.assertions)

Ejecutar Test PHPUnit:


Ejecutar solo los test: phpunitcapp/ Ejecutar los test y obtener reportes de cobertura: antphpunit Ejecutar los test, y obtener todos los reportes y mtricas

ant

Hacer TDD
TDD o Test Driven Design, Diseo dirigido por test; una forma ms fcil de entenderlo es llamarlo por su otro nombre, menos comn, Diseo dirigido por Ejemplos. Test = Ejemplo. Una vez recibidas las especificaciones del usuario (en forma de historias de usuario), se sigue el siguiente protocolo: Escribir la especificacin del requisito (el ejemplo, el test). Implementar el cdigo segn dicho ejemplo. Refactorizar para eliminar duplicidad y hacer mejoras. Rojo (hacer test que falla) Verde (implementar cdigo para que test pase) Refactorizar

Otra forma ms metafrica de ver el protocolo es:

Este ciclo es iterativo, ya que se empieza con una funcionalidad mnima, se refactoriza, y poco a poco se va aadiendo funcionalidad. O se va profundizando en los componentes / capas del sistema.

Ejemplo Uso TDD:


Historia de Usuario:

AQUI VA UN EJEMPLO DE UNA IMPLEMENTACIN TDD

Correccin de Incidencias - Bugs


Cuando se reporta un error, incidencia o bug ( comportamiento no deseado por el product owner), en un sistema desarrollado por TDD/BDD se sugiere seguir estos pasos: El reporte de la incidencia debe especificar las condiciones para poder reproducir el error. Y se deben evitar las ambigedades (como un requisito). Ejemplo 1: En la pgina X, no se est mostrando bien. Si el error ocurre siempre, y el desarrollador puede reproducir manualmente el error, no hace falta ms descripcin, pero sino, debe especificarse que se introdujo, o como se encuentra el estado del sistema para poder reproducir el error. Que es mostrarse bien? Debe evitarse la ambigedad. Ejemplo 2: En la pgina X, cuando meto un nmero negativo en el campo Y, al aceptar los datos y pasar al siguiente formulario la aplicacin muestra un mensaje de error indeseado o inesperado. Una vez que la incidencia est clara y el equipo de desarrollo pueda reproducir el error manualmente en el mismo entorno del usuario (qa, pre o produccin), se continua.

Las historias de usuario, contemplan como debe comportarse el sistema en esas condiciones? Si la respuesta es negativa, se pregunta al product owner cual es el resultado esperado en esas condiciones, y se escribe una nueva historia de usuario, al respecto. Si la respuesta es afirmativa, se debe tratar de copiar el estado o condiciones del entorno donde ocurri el error (produccin, pre, o qa) en el entorno de prueba para ejecutar la batera de test de aceptacin y test unitarios relativo al componente que falla. Si los test existentes no pasan, se debe identificar si hay una condicin del sistema que no estaba identificada en el reporte de la incidencia o en la historia de usuario original. Si los test existentes pasan, se debe escribir un nuevo test de sistema o un test de aceptacin que reproduzca el error de forma automtica. Si no es posible identificar el componente que presenta la falla, se escriben test de integracin que involucren menos capas del sistema, hasta poder aislar el componente que tiene la falla. Se escribe un test unitario que reproduzca la falla. Se hacen las modificaciones en el cdigo para corregir la falla.

En el ejemplo N 2, se puede identificar fcilmente que se trata de una validacin que no estaba contemplada. Y que puede resolverse rpidamente, sin hacer toda esta burocracia. En casos as donde el error y las condiciones son fciles de identificar, y fciles de arreglar, puede aplicarse el correctivo inmediatamente, sobre todo si la falla est en produccin o en pre y debe pasar pronto a produccin. Pero es recomendable luego cumplir con todo el protocolo, para que quede registrado el comportamiento deseado por el product owner en esas condiciones, y quede el test automatizado dentro de la batera de test, lo cual refuerza la fiabilidad y estabilidad del sistema.

Material de Referencia:
http://www.dirigidoportests.com/el-libro http://www.phpunit.de/manual/3.6/en/ http://symfony.com/doc/current/book/testing.html

Вам также может понравиться