¡Reconocimiento MVP Award 2018!

      10 comentarios en ¡Reconocimiento MVP Award 2018!

MVP Award

Hoy por la tarde he recibido un correo de Microsoft que decía:

mvp

Estoy muy ilusionado de recibir este reconocimiento a la labor de este tiempo en MSDN y estas ultimas semanas con el blog, solo espero poder seguir aprendiendo y estar a la altura de este galardón.

Es todo un honor para mi poder entrar a formar parte de este grupo de grandes profesionales, entre los que están muchas personas que admiro por su gran labor, como el gran Leandro Tuttini, el señor Williams Morales o don José M. Aguilar, cuyo blog Variable not found (de obligada lectura, mis dieces) me incito a abrir el mio.

Muchas gracias al programa MVP de Microsoft por darme este premio.

Muchas gracias a los compañeros que me aguantáis día a día me aguantáis hablando sobre proyectos interesantes, algunos incluso sin poder huir durante la ida y vuelta al trabajo (Eso lo sabe bien Rubén de MascandoBits, la otra persona que me incitó a abrir un blog, incluso haciendo algunas colaboraciones en el suyo, mis dieces también).

Pero sobre todo, millones de gracias a mi familia que me ha apoyado, y en especial a mi novia que es la que mas tiene que aguantar los días pegado a la pantalla del ordenador y la que más me apoya, sin ella, nada de esto sería posible.

 

Venciendo el miedo a las pruebas unitarias en .Net

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:

 

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:

 
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

Inyección de Dependencias en .Net Framework

Inyeccion de dependencias

Un mes ya… y hoy vengo a hablaros de la «Inyección de Dependencias» (DI). La inyección de dependencias consiste de manera resumida en evitar el acoplamiento entre clases utilizando interfaces. Gracias esto, conseguimos que cada clase tenga una función única, facilitando así el mantenimiento y el soporte de nuestro código.

Esto que puede parecer un poco lioso a simple vista, y puede parecer mucho trabajo, se puede conseguir fácilmente cambiando levemente nuestro patrón de diseño. Vamos a imaginar que tenemos una clase que lee unos datos desde una base de datos con Entity Framework («Database First» o «Code First«), y los envía por email:

 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using PostInyeccion.Models;

namespace PostInyeccion
{
    class Program
    {
        static void Main(string[] args)
        {
            GeneradorInformes generador = new GeneradorInformes();
            generador.GenerarInforme();
        }
    }

    internal class GeneradorInformes
    {
        internal void GenerarInforme()
        {
            //Obtenemos los datos desde el contexto
            using (PostDbContext contexto = new PostDbContext())
            {
                var profesores = contexto.Profesores.Include(x => x.Cursos)
                                                    .ThenInclude(x => x.Alumnos).ToList();
                
                //Trabajo de maquetacion
                //.......                           

                //Enviamos el correo
                var emailSender = new EmailSender();
                var envioOK = emailSender.Enviar(profesores);
                if(!envioOK)
                {
                    //Registramos el fallo en un log
                }
            }
        }
    }

    public class EmailSender
    {
        public bool Enviar(List profesores)
        {
            //Enviar correo
            return true;
        }
    }
}

En primer lugar, vamos a analizar los posibles problemas de esta clase:

  1. Baja mantenibilidad por el acoplamiento en entre clases: Es la propia clase la que instancia las que va necesitando, provocando que cualquier cambio en las clases "auxiliares" pueda cambiar el comportamiento.
  2. Dificultad para realizar pruebas unitarias: En el caso en el que queramos realizar pruebas unitarias, es requisito que todos los servicios estén activos. Desde el punto de vista de las pruebas, esto es nefasto, podemos no tener acceso al servidor de correo, o a la base de datos... Con este patrón, es muy difícil testear nuestra clase.

Inyección de Dependencias

Vamos a ver que pasa si refactorizamos la clase para inyectar las dependencias, de manera que no tengamos dependencias:

 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using PostInyeccion.Models;

namespace PostInyeccion
{
    class Program
    {
        static void Main(string[] args)
        {
            //Generamos la clase que hara el trabajo
            GeneradorInformes generador = new GeneradorInformes();

            //Obtenemos los datos desde el contexto
            using (PostDbContext contexto = new PostDbContext())
            {
                var profesores = contexto.Profesores.Include(x => x.Cursos)
                                                    .ThenInclude(x => x.Alumnos).ToList();

                //Instanciamos la clase de envio de emails
                var emailSender = new EmailSender();
                generador.GenerarInforme(profesores, emailSender);
            }
        }
    }

    public class GeneradorInformes
    {
        public  void GenerarInforme(List profesores, IEmailSender emailSender)
        {
            //Trabajo de maquetacion
            //.......
            
            //Enviamos el correo
            var envioOK = emailSender.Enviar(profesores); 
            if(!envioOK) 
            { 
                //Registramos el fallo en un log 
            }
        }
    }
}

interface IEmailSender
{
    bool Enviar(List profesores);
}

public class EmailSender : IEmailSender
{
    public bool Enviar(List profesores)
    {
        //Enviar correo
    }
}

Hemos conseguido una mayor mantenibilidad al abstraer totalmente a la clase "GeneradorInforme" de las labores propias de envío de correo y de obtención de datos. Y ahora es cuando me dices, "Pero no hace falta utilizar inyección de dependencias para conseguir lo que has conseguido...". Efectivamente, para simplemente desacoplar las clases, no sería necesario. Podríamos haberle pasado al método una instancia de EmailSender en vez de su interfaz pero... Si queremos hacer pruebas unitarias, eso no es suficiente. Seguiríamos con el problema de que si el servidor de correo esta caído, nuestra prueba fallaría. Ahí radica la potencia de trabajar inyectando dependencias. En nuestro proyecto de pruebas unitarias, simplemente tendríamos que añadir una nueva clase que implemente "IEmailSender" y que no se conecte a ningún servidor, o que simule la conexión.

En el caso del ejemplo, hemos inyectado las dependencias mediante un parámetro, pero esta solo es una de las maneras. Podemos inyectar dependencias de varias maneras:

  1. Inyección de dependencias en parámetros de constructor.
  2. Inyección de propiedades.
  3. Inyección de dependencias en parámetros de métodos.

Vamos a ver más detalladamente cada uno.

Inyección de dependencias en parámetros de constructor

 
var emailSender = new EmailSender();
GeneradorInformes generador = new GeneradorInformes(emailSender);
//--------------------------------------------------------------
public class GeneradorInformes
{
    //Dependencia para el envio de correos
    IEmailSender _emailSender;

    //Pasamos la dependencia en el construcor
    public GeneradorInformes(IEmailSender emailSender)
    {
        _emailSender = emailSender;
    }

    public void GenerarInforme(List profesores)
    {
        //Trabajo de maquetacion
        //.......

        _emailSender.Enviar(profesores);
    }
}

Inyección de propiedades

 
//Instanciamos la clase de envio de emails
var emailSender = new EmailSender();
GeneradorInformes generador = new GeneradorInformes();
generador.EmailSender = emailSender;
generador.GenerarInforme(profesores);
//-----------------------------------------------------
public class GeneradorInformes
{
    //Propiedad con la dependencia
    public IEmailSender EmailSender { get; set; }
    public GeneradorInformes()
    {
    }

    public void GenerarInforme(List profesores)
    {
        //Trabajo de maquetacion
        //.......

        EmailSender.Enviar(profesores);
    }
}

En este caso, hay que tener en cuenta que la dependencia no estará disponible durante el constructor, por si la necesitásemos.

Inyección de dependencias en parámetros de métodos

Es el caso que hemos visto en el primer ejemplo.

Contenedor IOC

La utilización de contenedores IOC (Inversion Of Control) nos abstraen de la necesidad de generar las clases cada vez. Simplemente es configurar un contenedor el cual nos sirva las dependencias que necesitamos en cada momento. Esto facilita mucho la labor de trabajo al no tener que gestionar nosotros mismos las clases. Existen bastantes sistemas IOC para .NET, pero en este caso, vamos a utilizar "Microsoft.Extensions.DependencyInjection".

Para eso, tenemos que añadir el paquete desde NuGet:

DI

O vía consola:

PM->Install-Package Microsoft.Extensions.DependencyInjection -Version 2.1.1

Ahora vamos a registrar los servicios (Asumo que tenemos un DbContext creado en base a los post de Entity Framework  Core), pero para ello, primero tenemos que crear el interfaz IGeneradorInformes y hacer que Generador de informes la implemente:

 
public interface IGeneradorInformes
{
    void GenerarInforme();
}

//.........

public class GeneradorInformes : IGeneradorInformes
//......

Una vez que lo tengamos, empezamos a registrar los servicios:

 
//Generamos la coleccion de servicios
IServiceCollection serviceCollection = new ServiceCollection();
//Registramos el DbContext
serviceCollection.AddDbContext(options=>
                options.UseMySql("Server=localhost;Database=postefcore;Uid=root;Pwd=root;"));
//Registramos el EmailSender
serviceCollection.AddSingleton();
//Registramos el generador de informes
serviceCollection.AddSingleton();

//Construimos el contendor IoC
var services = serviceCollection.BuildServiceProvider();

Después, simplemente necesitamos llamar a su metodo "GetService<T>()" para obtener una instancia de la clase concreta con todas sus dependencias inyectadas:

 
IGeneradorInformes generador = services.GetService();
generador.GenerarInforme();

Este sistema funciona muy bien en MVC 5 y MVC Core, ya que esta construido totalmente sobre el sistema de inyección de dependencias, pero es cierto que en aplicaciones que no sean MVC, hay que trabajarselo un poco. Digo esto porque necesitamos mantener activa una referencia a "services" para poder pedirle las clases. Esto lo podemos resolver bastante fácilmente con un tipo estático que almacene nuestra referencia:

 
using Microsoft.Extensions.DependencyInjection;
using System;

namespace PostInyeccion
{
    public static class Injector
    {
        static IServiceProvider _proveedor;

        public static void GenerarProveedor(IServiceCollection serviceCollection)
        {
            _proveedor = serviceCollection.BuildServiceProvider();
        }

        public static T GetService()
        {
            return _proveedor.GetService();
        }
    }
}

Veamos como usarlo en nuestro código:

 
static void Main(string[] args)
{
    //Generamos la coleccion de servicios
    IServiceCollection serviceCollection = new ServiceCollection();
    //Registramos el DbContext
    serviceCollection.AddDbContext(options =>
        options.UseMySql("Server=localhost;Database=postefcore;Uid=root;Pwd=root;"));
    //Registramos el EmailSender
    serviceCollection.AddSingleton();
    //Registramos el generador de informes
    serviceCollection.AddSingleton();

    Injector.GenerarProveedor(serviceCollection);
    //Obtengo clase desde el IOC
    IGeneradorInformes generador = Injector.GetService();
    generador.GenerarInforme();
}

Con esto, registraremos todas las dependencias al inicio de nuestro programa, y llamaremos a Injector.GetService<T>() cuando necesitemos utilizar una dependencia.

A simple vista, parece que es mucho trabajo y poca recompensa, pero en las siguientes entradas veremos las ventajas que aporta trabajar así cuando hablemos de las pruebas unitarias y del "Moking".

Puedes descargar el código de ejemplo desde este enlace.