Venciendo el miedo a las pruebas unitarias en .Net

Tiempo de lectura: 5 minutos

Test Unitario

Otro día más por aquí, y hoy vengo a hablaros de las «Pruebas Unitarias». Las pruebas unitarias son herramientas de testing para asegurar que nuestro código no cambia su funcionalidad pese a que hagamos cambios en él. Es decir, imaginemos que tenemos una librería matemática con unas operaciones simples:

 
public static class ProcesadorMatematico
{
    public static int Sumar(int primerNumero, int segundoNumero)
    {
        return primerNumero + segundoNumero;
    }
    public static int Resta(int primerNumero, int segundoNumero)
    {
        return primerNumero - segundoNumero;
    }
    public static int Multiplicacion(int primerNumero, int segundoNumero)
    {
        return primerNumero * segundoNumero;
    }
    public static int Division(int dividendo, int divisor)
    {
        return dividendo / divisor;
    }
    public static int Potencia(int numeroBase, int exponente)
    {
        return (int)Math.Pow(numeroBase, exponente);
    }
    public static int Raiz(int numeroBase, int exponente)
    {
        return (int)Math.Pow(numeroBase, 1 / exponente);
    }
}

Como se puede ver, es una clase muy simple de ver, entender, y probar su funcionamiento pero… ¿Que pasaría si una de estas operaciones básicas fallase por un cambio no comprobado? Pues probablemente, no pensaríamos que algo tan simple puede estar fallando… y eso que podemos haberlo cambiado incluso sin darnos cuenta…

Para evitar ese tipo de fallos, existen este tipo de herramientas, cuya finalidad es que, ante unos datos de entrada conocidos, si todo va bien, tenemos que tener unos datos de salida que podemos predecir y comprobar.

Pruebas Unitarias en Net Framework

Como habitualmente, crearemos un proyecto de consola:

ProyectoConsolaNetClasico

Y en el introduciremos la clase ProcesadorMatematico de la que acabamos de hablar. Una vez hecho eso, vamos a crear un nuevo proyecto en la solución, pero esta vez de pruebas unitarias:

PruebasUnitariasNetClasico

Con esto, veremos que se nos crea un proyecto nuevo dentro de la solución, con una clase por defecto:

 
[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestMethod1()
    {
    }
}

En ella vemos 2 decoradores, [TestClass] , el cual indica que esa clase va a ejecutar pruebas unitarias, y [TestMethod], el cual indica que ese método es una prueba unitaria. Da igual el nombre de la clase y de los métodos, siempre que tengan los atributos correspondientes.

Como en cualquier otro proyecto, tenemos que referenciar los proyectos que queremos usar:

referencia

Una vez hecho esto, podremos acceder a las clases añadiendo el using correspondiente. Vamos a crear un test para algunas operaciones, así que nos quedara algo como esto:

 
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using PostPruebasUnitarias;

namespace PruebasUnitarias
{
    [TestClass]
    public class PruebasProcesador
    {
        [TestMethod]
        public void TestSuma()
        {
            //Definimos las variables
            //Arrange
            var operador1 = 10;
            var operador2 = 11;

            //Ejecutamos la prueba
            //Act
            var result = ProcesadorMatematico.Sumar(operador1, operador2);

            //Comparamos resultados
            //Assert
            var valorEsperado = 21;
            Assert.AreEqual(valorEsperado, result);
        }

        [TestMethod]
        public void TestDivision1()
        {
            //Definimos las variables
            //Arrange
            var dividendo = 10;
            var divisor = 2;

            //Ejecutamos la prueba
            //Act
            var result = ProcesadorMatematico.Division(dividendo, divisor);

            //Comparamos resultados
            //Assert
            var valorEsperado = 5;
            Assert.AreEqual(valorEsperado, result);
        }

        [TestMethod]
        [ExpectedException(typeof(DivideByZeroException))] //Excepcion esperada
        public void TestDivisionExcepcion()
        {
            //Definimos las variables
            //Arrange
            var dividendo = 10;
            var divisor = 0;

            //Ejecutamos la prueba
            //Act
            var result = ProcesadorMatematico.Division(dividendo, divisor);

            //Comparamos resultados
            //Assert
            //En este caso, no deberiamos llegar aqui, la prueba correcta es una excepción de DivisionEntreCero
        }
    }
}

Para poder comprobar los resultados visualmente, la opción más cómoda es sacar la ventana de pruebas, para ello, vamos al menú Prueba->Ventanas->Explorador de pruebas unitarias. Esto nos añade una ventana al cuadro de herramientas:

VentanaPruebas

En ella, pulsaremos ejecutar todo, y veremos que nos muestra los resultados de las pruebas:

PruebasOK

Pero… que pasaría si por algún problema no pasa la prueba? Vamos a probarlo cambiando el método «Sumar» por :

 
public static int Sumar(int primerNumero, int segundoNumero)
{
    return primerNumero * segundoNumero;
}

Si volvemos a lanzar la prueba:

PruebaNOK

Efectivamente, las pruebas unitarias detectan rápidamente que algo no va bien…

Puedes descargar el código de ejemplo aquí.

Pruebas Unitarias en Net Core

Vamos a crear otro proyecto de consola, esta vez de NetCore:

consola .net core

Y en el vamos a añadir nuestra clase igual que antes. Una vez hecho, vamos a crear un proyecto de pruebas:

PruebasUnitariasNetCore

Y generamos una clase de pruebas como la anterior. Ejecutamos las pruebas exactamente igual que antes, y como podemos ver, los resultados son los mismos. Dejo un enlace al código fuente del proyecto para poder descargarlo.

Como se puede ver, las pruebas unitarias nos aseguran que nuestros cambios no comprometen el funcionamiento de nuestros programas, dándonos ese extra de tranquilidad al poder añadir pruebas para prácticamente cualquier cosa que se nos ocurra.

En futuros post, ampliaremos este tema tan versátil utilizando «Mocking» para simular las bases de datos y escribiendo clases «fake» para probar clases diseñadas según el patrón de inyección de dependencias

9 comentarios en «Venciendo el miedo a las pruebas unitarias en .Net»

  1. Hola,

    muchas gracias por el artículo. Solo avisarte de que lo revises porque algo se ha descontrolado. Hay párrafos repetidos y movidos de sitio.

    Saludos.

    Responder
    • Buenas tardes Antonio. Muchas gracias por el aviso, supongo que al actualizar WordPress como cambio el editor me ha hecho alguna perlada… Voy a revisar las entradas antiguas para dejarlas bien.
      Muchas gracias otra vez!!!
      EDITO: Ya lo he arreglado, efectivamente fue el cambio del editor de wordpress lo que me la lió… muchas gracias por el aviso!!

      Responder
  2. Hola, gracias por compartir. Tengo una duda, tengo una solución grande, dividida en capas, con muchos proyectos (winforms, WCF, negocio, accedo a datos..) ¿que consejo me brindas para empezar a agregar pruebas unitarias?

    Responder
    • Buenas tardes Matías,
      ¡Es una buena pregunta la verdad!

      Si no hay acoplamiento entre las diferentes clases, puedes empezar por cualquier parte, tal vez lo más interesante sea empezar añadiendo pruebas unitarias a la capa/proyecto ‘core’ de tu sistema que es el núcleo vital y de ahí ir subiendo hacia capas más exteriores. El criterio que seguiría es ir priorizar para añadir pruebas el código que se ejecuta con más frecuencia y desde ahí hacia el que menos se usa. Creo que con esto es la manera más rápida de aportar valor con las pruebas.

      Si por el contrario el código esta totalmente acoplado (hay ‘new’ de clases con funcionalidad compleja dentro de otras clases), lo que haría es empezar por las menos acopladas ya que para poder probarlas vas a tener que hacer un esfuerzo en desacoplarlas casi seguro. Si este es tu caso, te recomendaría echarle una lectura a los principios SOLID ya que hacer un código que funcione pero además sea de calidad ayuda enormemente en la tarea de añadir pruebas.

      Ten en cuenta que los formularios por ejemplo son algo difícil de probar. Hay herramientas para hacer pruebas de GUI pero personalmente yo no me metería con eso salvo que sea un requisito.

      No se si te he aclarado algo o te he dejado igual… Siente libre si tienes dudas más concretas de preguntar en los comentarios o a través del formulario de contacto (el formulario de contacto me envía un email directamente por lo que evitas poner datos en público).

      Un abrazo!

      Responder
  3. Claro y conciso Jorge, sigue así ya que hay mucho contenido sobre estos temas pero pienso que dar contexto de mas confunde, y contenido es muy bueno y claro como ya lo había mencionado.

    Saludos desde saltillo, coahuila, mx

    Responder

Deja un comentario