XUnit 1.0 - Usando ReSharper como Runner

Hoy me enteré de este lanzamiento que de manera particular lo estaba esperando. Hace un tiempo atrás cuando este proyecto estaba en pañales, estuvimos hablando un poco sobre él.

Recordemos que existen muchos frameworks para realizar Unit Testing, y XUnit es un proyecto particular, tiene diferencias bien marcadas con respecto a otros frameworks como por ejemplo NUnit. Si bien el creador de XUnit es el mismo que creó NUnit, la principal idea de la creación de otro framework de testeo fue alejarse de algunos aspectos intrínsecos que NUnit los tenía fuertemente heredados de su fuente de inspiración JUnit.


Descargar XUnit 1.0

Para correr los tests podemos utilizar diferentes runners:

  • xunit.console (se distribuye con los binarios de XUnit)
  • xunit.gui (se distribuye con los binarios de XUnit)
  • TestDriven (se integra con Visual Studio)
  • Resharper 3.1 (se integra con Visual Studio)

Aquí tienen una captura para que vean en acción a XUnit corriendo desde ReSharper:

Sintaxis en Rhino Mocks

Rhino Mocks es un excelente framework para realizar mocking en nuestras pruebas unitarias. Una de las buenas razones para usarlo es que no hace uso de strings para hardcodear los nombres de tipos, metodos, properties, etc, reduciendo entonces la posibilidad de error en tiempo de ejecución.

Despues de la versión 3.0.5 liberada hace un tiempo, la sintaxis para realizar mocking quedó un poco más fácil de leer y con menos posibilidades de error.

Al mirar este screencastintroductorio a Rhino Mocks te darás cuenta como se hacía antes. También salta a la vista que cualquiera puede olvidar de llamar al método VerifyCall() dejando libre la posibilidad de errores.  

        [Test]
        public void SigmoidalFunctionDerivative()
        {
            INet net = Mock<INet>();

            ITransferFunction tf = new SigmoidalTransferFuncion();

            Expect
                    .Call(net.Value)
                    .Return(5.0);

            Mocks.ReplayAll();

                //f’(net) = y * ( 1 - y )
                Assert.Equal(0.006648057, Math.Round(tf.Derivate(net), 9));

            Mocks.VerifyAll();
        }

Una forma más clara de hacerlo es:

        [Test]
        public void SigmoidalFunctionDerivative()
        {
            INet net = Mock<INet>();

            ITransferFunction tf = new SigmoidalTransferFuncion();

            using (Mocks.Record())
            {
                Expect
                    .Call(net.Value)
                    .Return(5.0);
            }

            using (Mocks.Playback())
            {
                //f’(net) = y * ( 1 - y )
                Assert.Equal(0.006648057, Math.Round(tf.Derivate(net), 9));
            }
        }

En estos ejemplos estoy usando un helper para el metodo Mock<T>() y la property MockRepository Mocks {get; set; }. Nada de otro mundo, y se pueda mejorar: 

public class TestFixtureBase
    {
        private MockRepository mocks;

        public MockRepository Mocks
        {
            get
            {
                if (mocks == null)
                { mocks = new MockRepository(); }

                return mocks;
            }
        }

        public T Mock<T>()
        {
            return Mocks.CreateMock<T>();
        }
    }

Existe aún así otra manera de hacer lo mismo, en vez de using, hacemos uso de delegados y la clase With (no es el de VB pero creo que por ahí vino la idea): 

        [Test]
        public void SigmoidalFunctionDerivative()
        {
            INet net = Mock<INet>();

            ITransferFunction tf = new SigmoidalTransferFuncion();

            With
                .Mocks(Mocks)
                .Expecting(delegate
                               {
                                   Expect
                                       .Call(net.Value)
                                       .Return(5.0);
                               })
                .Verify(delegate
                            {
                                //f’(net) = y * ( 1 - y )
                                Assert.Equal(0.006648057,
                                    Math.Round(tf.Derivate(net), 9));
                            });
        }

Particulamente elijo la opción 2, el usar la sintaxis con using.

xUnit.Net - Excepciones Esperadas

Para los que no estaban enterados, el autor de NUnit saca a la luz este nuevo Framework de unit testing. La intención de un nuevo Framework de Testing para .Net parecería querer reinventar la rueda, pero no lo es. Muchas practicas que se hacían en NUnit (y muchas de estas heredadas de JUnit) no van a estar disponibles -para bien de nuestro código según argumenta James Newkirk.

Uno de los cambios: No va más el ExpectedException. Y el argumento de su desaparición es válido: Puede que una linea de codigo arroje esa excepción, y no sea la linea de codigo que estamos esperando a que lo haga. Ahora debemos hacerlos así: 

        [Test]
        public void NeuronNotConnected()
        {
            INeuron n = new SigmoidalNeuron();

            Assert.Throws<BpnException>(
                delegate
                {
                    double foo = n.Net.Value;
                });
        }

Esta es la pagina del proyecto http://www.codeplex.com/xunit.

Y para correr los test con Visual Studio pueden usar http://www.testdriven.net/

SessionImpl, Unit Testing… y las flores siguen en la mesa

El truco de sacar el mantel y que el florero quede en el centro de la mesa intacto lo hizo el Sr. Fabio Maulo con una de las clases más importantes del core de NHibernate: SessionImpl.

En este post nos dice:

El la versión 1.2.x la session es de 5819 lineas de código.
Después de la modificación quedó en 3819.

Hagan las cuentas y son muchas lineas de código para tirarlas a la basura sin pensarlo! Claro, pero toda la tranquilidad viene del lado de las pruebas de unidad, que es practicamente lo que mantiene viva a la integridad en NHibernate.

Después de esto, uds sacarán sus conclusiones: si vale ponerle atención a las pruebas de unidad en nuestros proyectos, si es muy laborioso como para prestarle atención, o es una inversión y una tranquilidad sabiendo que la aplicación a medida que va creciendo en el ciclo de desarrollo se vá integrando bien.

Otra cosa a resaltar:

Hay muchos que para probar algo crean un proyecto de consola, prueban una clase y luego tiran el proyecto. Bueno… ya que hay que probar conviene escribir la prueba una sola vez y
verificar que siga funcionando siempre.

Totalmente de acuerdo, y hasta hace un tiempo yo hacia esto… me incluyo y lo reconozco. Al principio, al iniciarte en el arte de las pruebas de unidad puede que no se note la diferencia entre un test y una sesión de debug, puede que los tests los hagas mal, o puede que no sean muy legibles, pero todo se mejora con un poco de ejercicio.

Y lo más lindo del resultado de usar pruebas de unidad es que cuando terminás de hacer las modificaciones pertinentes, realizás las pruebas, hacés commit…y

puedo dormir tranquilo.