TFS, Xamarin y MSTests

Hace un tiempo vimos un pequeño truco para poder ejecutar tests en las builds de TFS para proyectos Windows Phone.

Me ha sido necesario hacer lo mismo con proyectos con Xamarin Android y Xamarin iOS y aquí os pongo mi experiencia y cómo lo he resuelto.

Requisitos

TFS on-site, es decir, un TFS instalado y administradro por ti. Para el servicio gratuito de  Visual Studio Online no vale esto, necesitas una máquina de Build Personalizada en la que pudieras instalar los plugins de Xamarin. Con Xamarin Starter instalado en el servidor y en cliente.

A testear (¿o es testar?)

Tanto para proyectos Android como iOS añadiremos una referencia a la dll Microsoft.VisualStudio.QualityTools.UnitTestFramework que andará por la ruta:

C:\Windows\assembly\GAC_MSIL\Microsoft.VisualStudio.QualityTools.UnitTestFramework\10.1.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll

De esta manera ya podremos usar MSTest en el proyecto. En nuestra máquina, podemos ejecutar tests sin ningún problema, crearlos y aplicar TDD si nos place (os lo recomiendo). Los problemas vienen cuando subimos todo este trabajo al TFS y se intentan ejecutar los tests en las builds.

Corrigiendo los problemas en el TFS

Ahora vamos a ver qué tenemos que hacer en cada plataforma, para que las builds puedan ejecutar nuestros proyectos de tests sin problemas.

Android

En el caso de proyectos de Android, seguramente la build nos habrá devuelto un error de este tipo:

The "CopyIfChanged" task failed unexpectedly. System.UnauthorizedAccessException: Access to the path 'Resources\Resource.Designer.cs' is denied.

Lo que debemos hacer es borrar del repositorio de código  el archivo Resource.Designer.cs del proyecto que contiene los tests.

Ahora vamos a usar el mismo truco que usamos con los tests de Windows Phone para que no nos salten excepciones del tipo TypeInitializationException o FileNotFoundException a la hora de cargar algunos assemblies y tipos necesarios.

1 Copiamos la dll Mono.Android.dll que puedes encontrar en "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\MonoAndroid\v4.0\" a un directorio local a la solución, vamos a llamar a ese directorio lib

2 Modificaremos el .csproj del proyecto de tests reemplazando:


<Reference Include="Mono.Android" />

por


<Reference Include="Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065">
<HintPath>..\lib\Mono.Android.dll</HintPath>
</Reference>

Y listo, la build de Android volverá  ejectuar los tests que tengáis definidos.

iOS

En el caso de Xamarin para iOS sólo vamos a tener que realizar los pasos 1 y 2 de Android pero con dlls diferentes:

1 Copiamos la dll monotouch.dll que puedes encontrar en "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\MonoTouch\v1.0\" a un directorio local a la solución, vamos a llamar a ese directorio lib

2 Modificaremos el .csproj del proyecto de tests reemplazando:


<Reference Include="monotouch" />

por


<Reference Include="monotouch, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065">
<HintPath>..\lib\monotouch.dll</HintPath>
</Reference>

Y listo, ya puedes ejecutar las builds y crear tests para tus desarrollos con Xamarin

Esta es la técnica que usamos en Wave Engine para testear la parte que está mas ligada a las plataformas.

¿Se te ocurre otra forma de hacerlo? A mi me da que con Jenkins también se puede hacer 😉

De hecho, Xamarin tiene sus instrucciones para configurar tu sistema de Integración Continua con TFS, Jenkins y tests con NUnit: http://blog.xamarin.com/continuous-integration-for-your-mobile-app/

Espero que sirva

Autor: Juan María Laó Ramos.