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


2 comentarios:

Fernando Claverino dijo...

Hola Sergio, felicitaciones nuevamente por el post. Me has motivado a escribir un poco algo que aprendí del mundo java para hacer las pruebas unitarias más fáciles.

http://toclasaas.blogspot.com/2009/08/como-hacer-el-unit-test-mas-facil.html

saludos!

Sergio Salanitri dijo...

Hola Fernando, muy interesante tu post. Sería bueno ver como aplica a .Net usando el framework Spring.Net
Con respecto a DDD estoy leyendo el libro DDD Quickly que lo podes bajar gratis de
http://www.infoq.com/minibooks/domain-driven-design-quickly