sábado, agosto 22, 2009

Introducción TDD III

Continuando con esta serie de posts, voy a describir el uso de una herramienta que me pareció muy útil para probar servicio Web y Rest, me refiero al SoapUI.
En este caso voy a describir la funcionalidad que tiene la herramienta para crear objetos mocks que simulen un servicio Web, en la documentación del SoapUI los denominan MockService.

Los objetos Mock son objetos que permite simular los servicios externos al código que queremos probar.
Por ejemplos si estamos probando una componente de acceso a datos necesitaríamos tener acceso a la base de datos, que esta contenga datos de prueba válidos etc, por lo tanto dependeríamos del estado de la base de datos, la conectividad a ella y tener los permisos necesarios. Una alternativa sería simular el comportamiento de la base de datos utilizando objetos simulados que tenga el comportamiento esperado para el sistema real antes determinado conjunto de datos de entrada.

Luego de esta breve introducción vamos a ver como implementar MockServices usando el SoapUI


Lo primero que debemos hacer es generar un proyecto SoapUI en base al WSDL del servicio que queremos simular. Le asignamos el nombre TestCreditRiskService y habilitamos las opciones “Create Test Suite” y “Create Mock Service” dejando los otros valores por defecto sin alterar.

En la ventana “Generate Test Suite” dejar las opciones por defecto.




Para hacer una prueba manual del servicio se utilizan los mensaje xml de entrada creado por la herramienta, por defecto se crea uno, pero se pueden crear todos los necesarios con le menú contextual sobre el nombre del servicio.






En este ejemplo el servicio original está corriendo en la máquina local y los datos válidos de prueba son dni=12345678 y dni=23456789, de lo cuales obtenemos reportes de riesgo crediticio diferentes.


Para agregar un objeto Mock para un servicio Web (MockServices) se puede utilizar el creado cuando

se generó el proyecto o bien con el menú contextual sobre la interfase.

Este MockServices implementa el patrón de Service Stub para acceder a la simulación el servicio web original o bien al servicio original, esto se camb

ia seleccionando el endpoint correspondiente.

Para el MockServices creado asignamos un Response simulado en base al Request2

Los endpoint asignados a los mockservices se puede ver directamente invocando en el navegador la url asignada al MockService.


Por lo tanto si vamos a nuestro request original podríamos ejecutar el mismo pero invocando al MockService creado.

Agregamos el endpoint de la interfase RiskClientServiceSoap para que use como interfase de entrada.






Una vez configurado podemos iniciar el servicio simulado con las opción Start.



El MockService ya está corriendo, el último paso de configuración es redireccionar nuestra interfase del servicio original al servicio simulado.




Conclusión:

Utilizando el SoapUI se pueden hacer pruebas unitarias de servicios web en un forma muy simple, además permite hacer pruebas de carga.
Con los MockService podemos además empezar a dsarrollar el código que lo invoca antes de que la implementación real del servicio esté disponible.
Obviamente que está situación es útil cuando el contrado ya está bien definido y la implementación real tenga los menores cambios para que no impacte lo que ya se hizo.






miércoles, agosto 19, 2009

Introducción TDD II

Pruebas unitarias con NUnit
A la hora de confeccionar el test unitario de una aplicación bajo NUnit, lo primero con lo que de debe contar como se mencionara anteriormente, es con los casos de test, luego se debe escribir el código de testeo, este código tiene una estructura especial y cuenta con una serie de atributos que serán interpretados mas adelante por el motor de NUnit. El código especialmente creado para este fin, contará con Assertions, que van a probar el correcto funcionamiento de la aplicación, en el caso de no tenerlos, el test fallara si el método testeado devuelve una excepción.

Asserts

Una aserción, o instrucción Assert, prueba una condición especificada
como argumento para el método Assert. Si la condición se evalúa como
true, no se produce ninguna acción. Si la condición se evalúa como
false, se produce un error en la aserción. Si la ejecución se realiza
bajo el depurador, el programa entra en el modo de interrupción.
Más información sobre Aserciones en el código administrado
Las aserciones son una base importante en los tests unitarios, si la aserción falla, se reporta el error. Si un test contiene mas de una aserción, las subsiguientes a aquella en donde se produce la falla no serán ejecutadas, ya que el test en ese caso ha fallado, es por esto que es más que recomendable, probar una sola aserción por test.

Las Aserciones deben ser utilizadas en aquellos casos en donde se requiera algún tipo de evaluación sobre un valor devuelto por un método, o por ejemplo en casos donde se evalúan condiciones en función del resultado de la ejecución de un método.

A modo de ejemplo, si se tiene un método que suma dos números, el test a realizar, será, la comprobación, del valor resultante de la ejecución del método, contra un valor esperado determinado. Existen diferentes tipos de Aserciones, que van a proveer al programador de la aplicación de test unitario, de la facilidad, para crear a partir la combinación de los mismos, test unitarios sólidos.

A continuación se enumeran los distintos tipos de aserciones provistas por Nunit. Y se recomienda visitar en link que se encuentra mas adelante, para obtener un detalle completo de los distintos métodos y sobrecargas que de la clase NUnit.Framework.Assert ofrece, agrupados por tipo.
Tipos de Aserciones:
• Equality Asserts
• Identity Asserts
• Compararion Asserts
• Type Asserts
• Condition Asserts
• Utility Methdo s
• String Assert
Para mas detalles
Atributos
Son utilizados por NUnit para la identificación de los tests, en versiones anteriores, la identificación se hacia en base a herencia y a partir de naming conventions, es a partir de la versión 2 de NUnit que la identificación de los test unitarios se da, a partir de ciertos atributos.

Estos atributos, están incluidos en el Namespace NUnit.Framework, cada clase que los use debe incluir el using correspondiente, y el proyecto debe referenciar a el assembly, nunit.framework.dll.
Para mas detalles
La Interface
El UNit se puede ejecutar de dos formas, utilizando los comandos de consola o utilizando la interfase gráfica, la primera opción es ideal para automatizar el proceso, por ejemplo desde un PostBuild en el Visual Studio .Net o desde una tarea de Nant.
Como se puede apreciar el resultado de la ejecución presenta los distintos tests unitarios dispuestos en forma de árbol.
Luego de la ejecución se puede apreciar por medio de un color el resultado del mismo.

Verde = OK

Amarillo = No se ejecutó.

Rojo = Falla

Hacia la derecha se puede apreciar por medio de una interface de solapas los logs de los tests, que proveen amplia información sobre los test unitarios ejecutados, y errores que se van produciendo.
Esta interface también brinda la opción de seleccionar los tests unitarios a ejecutar, y se recarga automáticamente cuando se recompila el código.





Creando el proyecto de pruebas unitarias en MS Visual Studio .Net

Una vez creado el proyecto de Test en MS VS .Net, que contendrá la o las clases con los métodos que ejecutará el NUnit, lo que sigue es:

En cada clase importamos el espacio de nombres agregan
do:

 using NUnit.Framework;



Establecemos el atributo que índica la clase que contiene las pruebas, con lo cual, previo al nombre de la clase agregamos "[TestFixture]", por ejemplo:

                                                   Contraer
 
namespace MyCompany.Application.Project.TestCases
{    
    [TestFixture]
    public class TestCase
    {
                      ...
    }
    ...
}
 
 

Podemos además incorporar un metodo que inicialice variables a utilizar indicándolo previamente con [SetUp]:

 Contraer
 
[SetUp] 
public void Init() 
{ 
      ... 
} 
 
  

Especificamos cuales son los métodos sin retorno

de resultados (void) de prueba que el NUnit deberá ejecutar con la cláusla [Test], ejemplo:

  Contraer
#region Test Method1

 
[Test]
public void TestMethod1()
{
 
      ...;
 
}
 
#endregion
 
 
    
 

El siguiente es un ejemplo simple:

  Contraer
 
using System;
 

Para ampliar el concepto de los Asserts se va dar un ejem

plo sobre su utilización.

Como se puede apreciar en el siguiente ejemplo, el método SetUp, quien cuenta con el atributo [SetUp], posee la lógica necesaria para crear los objetos que serán utilizados durante los tests unitarios.

Mas adelante, es posible distinguir el método BagMultiply, este es un test que cuenta con varios Asserts, como se puede apreciar en el código, por medio de estos 3 Asserts, se testea el buen funcionamiento del mismo.


En los dos primeros casos, los asserts son de comparación, como parámetros se pasan, en primer lugar el valor esperado y luego el valor resultante del método que se prueba.

Por último tenemos un assert que va a evaluar la condición que se pasa por parámetro.

Para este test, con cualquiera de los asserts que falle, el resultado del test será negativo.





Luego se compila el proyecto quedando preparado para ejecutarlo desde NUnit.


Conclusión:

Con esta herramienta se pueda ejecutar pruebas unitarias en forma automática.
Junto con herramientas de integración continua como el Hudson con un control de fuentes como SVN, de scripting de tareas con el Nant, de generación de mock objets como NMock se puede generar un entorno basico para automatizar las pruebas unitarias.

Comercialmente está el Team Fundation Server que permite generar los casos de test, hacer el deploy y automatizar las pruebas, el analisis de estas herramientas de este tipo queda para otro artículo.

Referencias:

  1. NUnit Framework, http://www.nunit.org


viernes, agosto 14, 2009

Introducción al TDD I

Pruebas unitarias

Introducción:


El diseño de un software es un factor muy importante pues afecta a todo el ciclo de vida del desarrollo y la calidad del software creado. Un buen diseño permite al sistema satisfacer principalmente los requisitos funcionales pero también los no funcionales como mantenibilidad, seguridad, performance, usabilidad etc. Existen varias técnicas de diseño cada una con sus características particulares. En este artículo vamos a describir los aspectos fundamentales del desarrollo de software basado en pruebas (TDD; por sus siglas en inglés).
Por lo tanto TDD no es una metodología de pruebas sino de diseño donde se comienza con el diseño y desarrollo de los casos de pruebas y luego con la implementación del código funcional hasta que las pruebas se puedan ejecutar sin errores.
Los casos de prueba además sirven para especificar los casos de uso en formato ejecutable y esta técnica permite diseñar el software en niveles de abstracción desde una granularidad chica hasta la más grande.

Beneficios de realizar las pruebas unitarias:

En cuanto al código
  • Es fácil de mantener.
  • Se torna más comprensible.
  • Tiende a estar mejor diseñado.
  • Antes de escribir código, fuerzan a detallar los requisitos de una manera útil.
  • Mientras escribe el código, evitan un exceso de funcionalidad. Cuando se pasan todos los casos de prueba, la función está completa.
  • Cuando se hace refactorización de código, aseguran que la nueva versión se comporta de la misma manera que la antigua.
  • Cuando se mantiene código, ayudan a asegurar que los cambios no alterarán código ajeno.
  • Cuando se escribe código en equipo, aumenta la confianza en que el código que se está a punto de enviar no va a romper el de otras personas, porque se pueden ejecutar las pruebas unitarias de ellos antes.
  • Los test unitarios actúan como documentación.
  • El conjunto de test unitarios proporciona constante retroalimentación de cada uno de los componentes.
  • La detección de errores se ve facilitada.
  • El tiempo de depuración se reduce.
  • El conjunto de tests actúa como una red de seguridad contra regresiones en los bugs.

Características de un buen Test:

  • Un test debe probar el qué y no el cómo, debe asegurarse que la funcionalidad del código a probar se cumpla en forma correcta y no prestar atención a como lo logra.
  • Es muy limitado en su alcance.
  • Se ejecuta y sucede de manera independiente.
  • Revela claramente su intención.
  • Debe poder ser ejecutado en forma automática cada vez que se modifique el código probado.
  • Usa ha menudo stubs y mock objects.
Desventajas de las pruebas unitarias manuales.

  • Se puede escribir una aplicación de prueba para hacer el testing. Si luego de varias semanas se quiere volver a hacer el testing el código ha sufrido tantas modificaciones que seguramente la aplicaciónd e prueba inicial ya no sirva y tenga que volver a construirse.
  • En proyectos grandes podrá haber decenas de clases y muchas librerias.Es muy dificil escribir pruebas separadas por cada una de las clases en el proyecto y mantener todas ellas para futuros pruebas.
  • Probar apliaciones requiere un tester humano.Se puede probar varias posibilidades al principio, pero es dificil recordar todos los casos para repetir en el futuro, se deberían documentar aparte teniendo que mantener los casos de pruebas y la documentación.
  • Cuando la prueba es manual, el tester debe verificar el resultado de la misma y por lo tanto deber tener todo el conjunto de resultados posibles para cada prueba
  • Es muy poco practico repetir todo el tiempo todos los casos manualmente antes de que salga un release. Esto llevaria muchas horas o días para completar las pruebas unitarias de todas las piezas de código.
  • La ejecución de pruebas unitaria en forma manual es muy tedioso y tendiente a errores.
  • Utilizando Test Driven Development TDD las pruebas son automáticas y autodocumentadas.

Herramientas

Existen en el mercado muchas herramientas que permiten realizar pruebas unitarias, la mas utilizadas son

Herramienta
Plataforma
Comentarios
NUnit
http://www.nunit.org/
.Net Framework 1.0,1.1,2.0
Free, modo consola o interface gráfica
TestDriven

http://www.testdriven.net/


.Net Framework1.0,1.1,2.0,3.0
Misma funcionalidad del NUnit como adin del VS.net.Los resultados se visulizan en modo texto en el VS.Net
JUnit

http://www.junit.org/


Java
Stand alone o integrado a varios IDEs (Eclipse, java Builder etc)
vbUnit

http://www.vbunit.com/


Visual Basic 6.0
Comercial, integrada con el VS VB 6.0
ASPUnit

http://aspunit.sourceforge.net/


ASP.Net
Permite realizar casos de prueba para el front end de ASP.Net (proyecto open source suspendido)
TFS
http://msdn.microsoft.com/en-us/teamsystem/default.aspx


.Net framework 2.0,3.0 y 3.5
Integrado con algunas versiones del Visual Studio Team System 2005/2008.
SoapUI
http://www.soapui.org

Java
Permite ejecutar pruebas unitarias de consultas SOAP y REST.

SUNit
http:\\sunit.sourceforge.net

Smaltak
El padre de todas las herramientas xUnit.

Conclusión

Las pruebas unitarias son un tema muy importante para garantizar la calidad del código que estamos creando. Usando una metodología de diseño y herramientas adecuadas este proceso se podría integrar para que en forma automática se ejecuten las pruebas unitarias ante cada subida al repositorio de código centralizado.Para ello se debería integrar con sistemas de control de versiones. Agregando un sistema de revisión de código automática junto se puede garantizar la alineación del código a estándares de codificación que mitigan problemas comunes de la aplicación de malas prácticas. Este tema está fuera del alcance del TDD pero si de las metodologías de desarrollo.

Referencias


  1. Testing object-oriented systems: models, patterns, and tools, Addison-Wesley

  1. Continuous integration, Martin Fowler, http://martinfowler.com/articles/continuousIntegration.html

  1. Extreme Programming XP , http://xprogramming.com/index.php

  1. Introducción a Scrum, http://www.mountaingoatsoftware.com/scrum

  1. Agile Manifiesto, http://agilemanifesto.org/



miércoles, agosto 05, 2009

Integration Patterns

Este es el titulos de unos de los libros de Patterns & Practices que resumen en un proyecto ficticio un diseño aplicando gran variedad de patrones de integración.
El libro se lo puede bajar en formato pdf en el sitio de P&P.

http://msdn.microsoft.com/en-us/library/ms978729.aspx

En la siguiente presentación hice un resumen de este libro.

Resumen Integration Patterns

Otra importante fuente de información sobre el tema es el sitio de Patterns and Best Practices for Enterprise Integration (http://www.eaipatterns.com/) que tambien tiene su libro.
Este sitio es muy interesante porque tiene los patrones clasificados en varias categorias y stencils de visio con esquema sobre este tipo de patrones.