Uso de TestCaseSource en NUnit

 
Con NUnit bajo .NET si deseamos crear TestCase que pasen sucesivos arrays a un método nos veremos en un dilema, puesto que a los atributos en .NET no se les puede pasar variables dinámicas. Así, el siguiente código ni siquiera compilará:
[TestCase(new[] { "s", null })]
public void IEnumerable_SameEnumerationIsProvided_ReturnsTrue(IEnumerable<string> model) {
// ...
}
El compilador nos devolverá el mensaje:
An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type.
Podríamos entender que new [] {“”} no es constante… Pero lo cierto es que lo siguiente sí funciona:
[TestCase(new[] {"1", "4", null}, new[] {"1", null, "4"})]
[TestCase(new[] {"s", null}, new[] {null, "s"})]
public void Enumerable_EquivalentEnumerationIsProvidedWithNullElement_ReturnsTrue(IEnumerable<string> model, IEnumerable<string> comparable) {
// ...
}
Queda pendiente averiguar en que consiste el error, pero nos vemos en la necesidad de buscar alternativas. Una puede ser el uso de TestCaseSource, un atributo del framework  NUnit que permite indicar una fuente de datos para los tests. Sus dos variantes permiten especificar un miembro (propiedad, método,  campo, estático o dinámico…) de la propia clase donde esta el método de prueba o en otra clase distinta. Como veremos más adelante, podemos incluso devolver u objeto cuyos miembros tengan ciertos nombres (se examinaran mediante reflexión), y podremos indicar argumentos, categorías, resultado esperado o otros datos de la prueba.
En nuestro ejemplo queremos probar que se enva un correo con adjuntos. El modo más sencillo seria:
public string[][] Adjuntos=new [] {new [] {@"C:\tmp.dat"}};

[TestCaseSource("Adjuntos")]
public void AdeqMailComposer_FileAttachementProvided_CallToSenderWrapWithOneAtachments(string[] attachments) {
// ...
}
Nota: procuro evitar usar cadenas para especificar nombres de clases, propiedades y demás porque impiden usar las herramientas  de refactorización más habituales y es una costumbre que facilita los errores. En este caso no aparenta haber mejor solución. Si usamos Resharper y dado que tiene integración una buena integración con NUnit, nos avisara de posibles errores.
Hemos resulto el caso, pero seguimos investigando…

Nótese que el parámetro es un array de strings, así que a NUnit le tendremos que pasar un array de arrays de strings. Esto hace que en el caso de tener varios de tipo array acabemos con interminables arrays multidimensionales. Así que podemos optar por algo más complejo.
En este ejemplo nuestro TestDataSource devolverá una enumeración de datos, conjuntamente con algunos metadatos que indicarán los resultados esperados. Como indica la documentación, los metadatos se pueden indicar devolviendo una clase con las propiedades Arguments, Categories, ExpectedException… pero NUnit ya nos proporciona una clase con dichas propiedades, y además un interface fuent. Así que el resultado puede ser:
public  IEnumerable<TestCaseData> Adjuntos () {
yield return new TestCaseData(new[]{@"c:\tmp.*"}, new[]{@"c:\tmp.dat"});
}

[TestCaseSource("Adjuntos")]
public void AdeqMailComposer_FileAttachementProvided_CallToSenderWrapWithOneAtachments(string[] attachments, string [] expected) {
// ...
}
Nuestro Adjuntos() se ha limitado a devolver  los parámetros a pasar al método, pero si la lógica de la prueba es sencilla, podemos pasar más datos:
public  IEnumerable<TestCaseData> Adjuntos () {
yield return new TestCaseData(new[]{@"c:\tmp.*"}, new[]{@"c:\tmp.dat"}).Returns(true).SetDescription("A wildcard file mask is provided");
yield return new TestCaseData(null , new[] { @"c:\tmp.dat" }).Throws(typeof(ArgumentNullException)).SetDescription ("An exception is expected").SetName("Null attachment is provided");
}

[TestCaseSource("Adjuntos")]
public bool MailComposer_FileAttachementProvided_CallToSenderWrapWithOneAtachments(string[] attachments, string [] expected) {
// ...
// assert
return Sender.SendWasCalled("pepejuan@gmeil.com", "Tema del mensaje", "Este es un mensaje", expected);
}
 Image
Como se puede ver en la captura, cuando el test lanza una excepcion en el IDE se nos muestra el valor de la propiedad Description. Si usamos (como debemos) nombres descriptivos para los test esto será contraproducente, pero puede sr útil si el código de las pruebas es siempre el mismo y son los datos los que aportan significado a la prueba.
Otro problema reside en que los métodos que generan los conjuntos de datos mencionados en TestCaseSource se ejecutan antes de  los métodos de inicialización de test (marcados con [TestFixtureSetUp],   [SetUp] o clases  [SetUpFixture]) lo que puede hacer de nuestros métodos CaseSource un engorro.
Anuncios
Tagged with: , , ,
Publicado en Programacion

Deixa a túa opinión

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s