Pruebas unitarias, acceso a ficheros y async para Windows 8


Crash Dummy Label
Cuando desarrollas Apps para Windows 8 u 8.1 y usas pruebas unitarias, en algún momento te encuentras con la necesidad de cargar un archivo para realizar una prueba. Parece una tontería, pero si juntas estas tres cosas puedes estar un buen rato hasta que consigues ponerlo todo en marcha.

Las pruebas unitarias de aplicaciones de la tienda Windows se realizan en proyectos especiales que no tienen acceso a toda la librería .Net, sino al subconjunto que tenemos para Windows RT. Que los test se realicen en un entorno limitado como el de producción es lo ideal, pero nos va a dificultar hacer algunas cosas que solemos hacer fácilmente en otros entornos de test, como por ejemplo leer archivos distribuidos con nuestras pruebas.

Empecemos por ejemplo con el siguiente test:

[TestMethod]
public void TestPlainXmlList()
{
    string xml = "<items><item name='one'/><item name='two'/></items>";
    var testable = new TestableClass();
    IEnumerable<string> items = testable.ListItems(xml);
    Assert.IsNotNull(items);
    Assert.AreEqual(2, items.Count());
}

Si ahora queremos realizar la prueba con un archivo que tenemos dentro del test, tendremos que cargarlo y no tenemos acceso a una clase File para cargar el archivo desde el disco. Tendremos que utilizar un StorageFile del API de Windows 8.

Como habitualmente, vamos a añadirlo al proyecto de pruebas y darle un valor “Copy if newer” en las propiedades del fichero:

Unit Test Files Windows 8

Ahora tenemos que abrirlo desde el test para poder enviar el contenido a nuestro método, los archivos que desplegamos con nuestra aplicación están en Windows.ApplicationModel.Package.Current.InstalledLocation. Es un StorageFolder y lo podemos usar como en cualquier App de Windows 8:

[TestMethod]
public async void TestLoadLargeXml()
{
    string largexml;

    var folder = Windows.ApplicationModel.Package.Current.InstalledLocation;
    var file = await folder.GetFileAsync("Files\\test1.xml");
    using (var fileopen = await file.OpenReadAsync())
    {
        using (var stream = fileopen.AsStreamForRead())
        {
            using (var r = new StreamReader(stream))
            {
                largexml = r.ReadToEnd();
            }
        }
    }

    var testable = new TestableClass();
    IEnumerable<string> items = testable.ListItems(largexml);
    Assert.IsNotNull(items);
    Assert.AreEqual(60, items.Count());
}

Como en Windows 8 tenemos muchos métodos asíncronos, hemos tenido que utilizar las palabras async/await pues las operaciones con archivos son asíncronas, pero tal como está escrito el método de test vamos a encontrarnos un problema: no aparecerá el método en el listado de pruebas y no tendremos manera de probarlo.

Los métodos async void no se pueden probar directamente

Esto es así porque un método declarado async void no es awaitable, simplemente se ejecuta en un hilo aparte en modo “fire and forget”, así que el framework de test no podrá saber cuándo ha acabado y lo ignora.
Para que sea awaitable bastará con que el valor de retorno sea una Task en lugar de void, tal que así:

[TestMethod]
public async Task TestLoadLargeXml()

A partir de este momento podremos ejecutar las pruebas sobre nuestros métodos de Windows 8/8.1.
Ahora sólo falta que algún día las pruebas funcionen bien en el VSOnline para tener todo lo que necesitamos para probar nuestras Apps.

Feliz testing!

Anuncios

Responder

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