Nota del autor

Si la entrada que estás leyendo carece de imágenes, no se ve el vídeo que teóricamente lleva incrustado o el código fuente mostrado aparece sin formato, podéis conocer los motivos aquí. Poco a poco iré restableciendo la normalidad en el blog.
Este blog es un archivo de los artículos situados previamente en Lobosoft.es y ha dejado de ser actualizado. Las nuevas entradas pueden encontrarse en www.lobosoft.es. Un saludo,
Lobosoft.

domingo, 2 de marzo de 2008

Asserts en NUnit

En un post anterior introducía los atributos con que podíamos etiquetar nuestras clases y métodos de prueba para que NUnit pudiese así reconocerlos y usarlos. Hoy veremos cómo podemos determinar si una prueba ha sido superada o no.


Las aserciones (asserts) son la parte central de la prueba en todos los frameworks xUnit. NUnit nos proporciona la clase Assert, que consta de una serie de métodos estáticos que nos permitirán validar si una determinada prueba ha sido superada o no. Hay que tener en cuenta que los métodos de Assert provocan una excepción si la prueba no ha sido superada, por lo que si en nuestro método hacemos varias llamadas a validaciones de Assert, aquellas que estén tras una prueba no superada no serán ejecutadas. Por esto, es conveniente no situar demasiadas validaciones en un único método, o estaríamos ocultando, aunque fuese temporalmente, la existencia de otros errores en la codificación.


Los métodos de la clase Assert pueden agruparse según su funcionalidad en:

Aserciones de igualdad: evalúan si dos argumentos son iguales. Los métodos están sobrecargados para mayor comodidad nuestra, de modo que puedan pasársele los valores a comprobar sin tener que llevar a cabo previamente una operación de boxing. Ejemplos de este tipo de aserción son:


[csharp]Assert.AreEqual( int expected, int actual );
Assert.AreEqual( int expected, int actual, string message );
Assert.AreEqual( int expected, int actual, string message, params object[] parms );
// unos pocos métodos más...
Assert.AreNotEqual( decimal expected, decimal actual );
Assert.AreNotEqual( decimal expected, decimal actual, string message );
Assert.AreNotEqual( decimal expected, decimal actual, string message, params object[] parms );[/csharp]

Aserciones de identidad: comprueban si los dos argumentos están referenciando al mismo objeto.

[csharp]Assert.AreSame( object expected, object actual );
Assert.AreSame( object expected, object actual, string message );
Assert.AreSame( object expected, object actual, string message, params object[] parms );

Assert.AreNotSame( object expected, object actual );
Assert.AreNotSame( object expected, object actual, string message );
Assert.AreNotSame( object expected, object actual, string message, params object[] parms );[/csharp]

También tenemos un método para comprobar si un objeto está contenido en un array o lista:

[csharp]Assert.Contains( object anObject, IList collection );
Assert.Contains( object anObject, IList collection, string message );
Assert.Contains( object anObject, IList collection, string message, params object[] parms );[/csharp]

Aserciones de comparación: nos permiten comprobar si el valor de un parámetro es mayor o menor que el del otro.


[csharp]Assert.Greater( float arg1, float arg2 );
Assert.Greater( float arg1, float arg2, string message );
Assert.Greater( float arg1, float arg2, string message, object[] parms );

Assert.Greater( IComparable arg1, IComparable arg2 );
Assert.Greater( IComparable arg1, IComparable arg2, string message );
Assert.Greater( IComparable arg1, IComparable arg2, string message, object[] parms );

Assert.Less( float arg1, float arg2 );
Assert.Less( float arg1, float arg2, string message );
Assert.Less( float arg1, float arg2, string message, object[] parms );

Assert.Less( IComparable arg1, IComparable arg2 );
Assert.Less( IComparable arg1, IComparable arg2, string message );
Assert.Less( IComparable arg1, IComparable arg2, string message, object[] parms );[/csharp]

Aserciones de tipo: nos permitirán validar si el objeto pasado por argumento pertenece a un tipo de dato determinado:


[csharp]Assert.IsInstanceOfType( Type expected, object actual, string message );
Assert.IsNotInstanceOfType( Type expected, object actual, string message );
Assert.IsAssignableFrom( Type expected, object actual, string message );
Assert.IsNotAssignableFrom( Type expected, object actual, string message );[/csharp]

Pruebas de condición: permiten comprobar si se da una determinada condición en el parámetro que le pasamos. Por ejemplo, si su valor es nulo, verdadero o falso, o si está vacío.


[csharp]Assert.IsTrue( bool condition, string message );
Assert.IsFalse( bool condition, string message );
Assert.IsNull( object anObject, string message );
ssert.IsNotNull( object anObject, string message );
Assert.IsNaN( double aDouble, string message );
Assert.IsEmpty( string aString, string message );
Assert.IsEmpty( ICollection collection, string message );
Assert.IsNotEmpty( string aString, string message );
Assert.IsNotEmpty( ICollection collection, string message );[/csharp]

Métodos de utilidad: Los métodos de utilidad permiten extender nuestro framework de pruebas o cambiar su funcionamiento normal. El primero de ellos es Fail(), y nos permitirá generar “fallos controlados” para crear nuestras propios métodos de aserción, personalizados y específicos para nuestros tests.


[csharp]Assert.Fail();
Assert.Fail( string message );
Assert.Fail( string message, object[] parms );[/csharp]

Por ejemplo, en el siguiente código validamos si un string contiene un valor determinado:

[csharp]public void AssertStringContains( string expected, string actual )
{
AssertStringContains( expected, actual, string.Empty );
}

public void AssertStringContains( string expected, string actual, string message )
{
if ( actual.IndexOf( expected ) > 0 )
Assert.Fail( message );
}[/csharp]

Por otro lado tenemos el método Ignore(). Ignore nos permite ignorar una determinada prueba de forma dinámica. Puede usarse en métodos de [Test], [Setup] o [Fixture Setup], pero los propios creadores de NUnit recomiendan usarlo en casos muy determinados, ya que podemos llevar a un comportamiento algo anárquico en las pruebas, haciendo difícil distinguir qué estamos ejecutando en un determinado momento, y qué no.


Por último, indicar que la clase StringAssert proporciona varios métodos extra para la realización de pruebas sobre strings.


[csharp]StringAssert.Contains( string expected, string actual, string message );
StringAssert.StartsWith( string expected, string actual, string message );
StringAssert.EndsWith( string expected, string actual, string message );
StringAssert.AreEqualIgnoringCase( string expected, string actual, string message );[/csharp]

Los ejemplos de esta entrada han sido tomados de la documentación oficial de NUnit 2.4.6.


Actualización (8 de abril de 2008): 

El blog registra una nueva entrada el 3 de abril de 2008 sobre Cheat Sheets, en concreto recogiendo una "hoja de trucos" o guía de Test-Driven Development, disponible para su descarga en formato PDF.

2 comentarios:

  1. Saludos.
    Bastante buena la referencia de los Assert. Estoy comenzando a realizar pruebas con Nunit, y tu ayuda se agradece.

    ResponderEliminar
  2. Muy buenas WeberGer.

    Me alegra que te sirva de ayuda la entrada. Hay algunas otras dedicadas a las pruebas unitarias, y de hecho quiero escribir en breve algo más sobre cobertura de código y buenas prácticas de desarrollo.

    Saludos.

    ResponderEliminar