Usando NUnit
Pruebas al Código en .NET

Fecha: 06/Febrero/2004 (06/Feb/2004)
Autor: Gonzalo Antonio Sosa M. e-mail


            Hoy en día las unidades de prueba (unit testing) se han convertido en una poderosa herramienta de pruebas al código,  ganando popularidad día con día, sobre todo en las empresas dónde los proyectos de software comúnmente alcanzan varios niveles de complejidad.  Unit Testing, es una de la más importantes  prácticas de  la metodología de programación XP (eXtreme Programming).

 

Sobre Unit Testing

     Cuando escribimos código no lo hacemos de forma perfecta desde la primera vez, la compilación misma del proyecto es la primer prueba a nuestra aplicación. El compilador verifica la sintaxis e indica las líneas dónde ha encontrado errores. Es una gran ayuda pero termina ahí. El programa puede y ciertamente contendrá errores, muchos de los cuáles son visibles sólo hasta el tiempo de ejecución de la misma. Tenemos entonces que regresar al código, buscar la línea del error y corregirlo, algo que aumenta los tiempos de desarrollo. No podemos eliminar todos los errores, pero sí es posible reducirlos a un nivel más aceptable.

     Aquí es dónde entran las Unit Testing. Ayudándonos a buscar errores escribiendo pruebas. Estas pruebas son programas, métodos actualmente. Ellos prueban cada parte del proyecto y verifican si están trabajando correctamente.

     Algunas veces no deseamos escribir pruebas, sobre todo al principio, pensamos que escribirlas es redundante, para que hacerlo sí el código funciona bien, el problema es que no siempre es así. Aun escribiendo las clases más sencillas estas son propensas a errores.

     Es verdad que en términos de escribir código es más el tiempo que se consume al escribir código y pruebas que sólo código, pero hacerlo tiene sus remuneraciones. No escribir pruebas es más rápido sólo cuándo se hace sin errores.

    Unit Testing es una práctica muy importante sobre todo en el mundo empresarial, dónde los resultados esperados son bastante complejos. El dejar muchos errores en las aplicaciones finales conlleva desarrollos más lentos lo que evidentemente no son nada favorables para las empresas.

    Existen muchas otras herramientas de pruebas al código además de la mencionada NUnit. Existen para los más variados lenguajes tales como: JUnit para Java, PUnit para Phyton, DUnit para Delphi, etc.

Un poco más...

    Si ponemos como ejemplo una clase llamada Cálculos, dónde uno de los métodos se encarga de dividir dos números y devolver el resultado. El conjunto de pruebas deberá consistir en muchas operaciones simulando los casos más excepcionales, como la división sobre 0.

    Estas pruebas de realizarse de forma tradicional, esto es ejecutando la aplicación, cuando el proyecto es considerablemente extenso podrá tomar bastante tiempo el realizarlas; o bien, con un solo click, usando las unidades de prueba. Ejecutándose automáticamente todo el conjunto de pruebas y devolviendo los resultados de las pruebas en simples true o false, sí estas se han pasado o no.

 Sobre Nunit

    Inicialmente portada de JUnit (Java Unit, unidad de pruebas para clases en Java), esta herramienta de pruebas para .NET se encuentra en su segunda revisión mayor, la versión 2. Enteramente escrita en C#, ha sido rediseñada para tomar ventaja de muchas de las características de los lenguajes .NET, por ejemplo atributos personalizados y otras capacidades relacionadas con la reflexión. Hay que resaltar que esta utilidad es de distribución libre, en la página del proyecto (http://nunit.sourceforge.net) puedes encontrar el código fuente de esta gran herramienta.

Una sencilla prueba

    Vamos a ejemplificar de manera general cómo se realizan las pruebas, ayudándonos para ello de una clásica clase "Cuenta". Antes de comenzar con el código:

    El ensamblado nunit.framework contiene el espacio de nombres NUnit.Framework, el cuál contiene los métodos estáticos (shared en visual basic .Net) que usaremos para conocer el comportamiento de los métodos de la clase cuenta.

El código de la clase cuenta:

using System;

namespace Banco
{
    public class Cuenta
    {
        private float balance;

        public Cuenta(){}

        public void Deposito(float Cantidad)
        {
            balance += Cantidad;
        }

        public void Retiro(float Cantidad)
        {
            balance -= Cantidad;
        }

        public void Transferencia(Cuenta Destino, float Cantidad)
        {
        }

        public float Balance
        {        
            get
            {
                return balance;
            }
        }
    }
}

El código de la clase CuentaTest:

//Importamos los espacios de nombres 
using System;
using NUnit.Framework;
namespace Banco
{
	[TestFixture] // Establecemos el atributo que índica la clase que contiene las pruebas.
	public class CuentaTest
	{
		public CuentaTest(){}

		[Test] //Especificamos cuál es el método de prueba.
		public void Transferencias()
		{
			//creamos la cuenta origen con un saldo de 200.00
			Cuenta origen = new Cuenta();
			origen.Deposito(200.00F);

			//creamos la cuenta destino con un saldo de 150.00
			Cuenta destino = new Cuenta();
			destino.Deposito(150.00F);

			//transferimos 100.00 de la cuenta origen a la destino
			origen.Transferencia(destino, 100.00F);

			//sí todo ha salido bien, debemos tener
			//un balance de 250.00 en la cuenta destino
			//y de 100.00 en la origen
			Assert.AreEqual(250.00F, destino.Balance);
			Assert.AreEqual(100.00F, origen.Balance);
		}
	}
}

    Antes  de continuar hay que mencionar que el atributo [Test] es el que indica a NUnit qué método está marcado para prueba dentro de la clase que ha sido establecida con [TestFixture]. Este método debe respetar una cierta signatura.

    public void MethodName()

    El Método estático AreEqual de la clase Assert, compara dos tipos, si no son iguales genera una Exception del tipo AssertException. Este método tiene varias sobrecargas que facilitan este tipo de comparaciones.

Ahora,

Obtenemos una barra de color rojo, con varios mensajes de error. Todo normal, ya que el método de prueba que hemos escrito contiene dos líneas que verifican que los valores obtenidos dentro de las operaciones sean los que se esperan.

        Assert.AreEqual(250.00F, destino.Balance);
     Assert.AreEqual(100.00F, origen.Balance);

    Y al no contar con código dentro del método de "Transferencia" los valores nunca se equilibran al realizar las operaciones.

Ahora, sin cerrar la ventana de la GUI de NUnit, modificamos el método de "Transferecia" con:

    public void Transferencia(Cuenta Destino, float Cantidad)
    {
        Destino.Deposito(Cantidad);
        Retiro(Cantidad);
    }

Para terminar

    Este ha sido un ejemplo muy sencillo, y los conjuntos de pruebas pueden ser tan extensos como se requieran.

    Debido a que las posibilidades de uso son bastante extensas no es posible abarcar todas ellas aquí. Sin embargo, espero que este ejemplo ayude a aclarar un poco el uso de esta herramienta. En la guía de inicio rápido que se descarga con NUnit, se habla con mayor profundidad de la mayoría de estas opciones.

    Para mayor información sobre NUnit, además de la guía de inicio rápido que se mencionó, tenemos la documentación que se presenta en la página del proyecto.

Saludos...


ir al índice

Fichero con el código de ejemplo