sábado, 29 de enero de 2011

Primeros pasos con Moq

Aprovecho que en los últimos días los compañeros Luís Ruiz Pavón y Bruno Capuano han escrito sendos artículos sobre Moles ( aquí y aquí ) para hacer una pequeña introducción a otro framework de mocking llamado Moq.

Lo primero que tenemos que hacer es bajarnos la dll de su web . Una vez hecho esto ya podemos incluir la librería (Moq.dll ) en nuestro proyecto de test.

El código que vamos a testear se compone de una clase llamada AssetManager que tiene una dependencia a IDAO, una interfície para definir la manera en que se persistirán los objetos, ya sea en una base de datos, en un fichero o en memoria. Es esta interfície la que "mockearemos", evitando así tener que codificar una implementación para testear AssetManager.

ClassDiagram1

Lo primero que vamos a hacer es crear un stub para la función SaveAsset de IDAO. Para tener clara la diferencia entre un Mock y un Stub, consulta este artículo de Martin Fowler.

Veamos el código para testear esta función:

[TestMethod]
public void SaveAsset_returns_true()
{
   
var mockDao = new Mock<IDAO>();
   
AssetManager assetManager = new AssetManager(mockDao.Object);

    Asset asset = new Asset();
   
mockDao.Setup(dao => dao.SaveAsset(asset)).Returns(true);

    Assert.AreEqual(true, assetManager.SaveAsset(asset));
}

Como podemos ver estamos creando un stub de nuestra interfície IDAO indicando que cuando se llame a la función SaveAsset nos devuelva el valor true. Así, al invocar al método SaveAsset de la clase AssetManager, que a su vez llama al método SaveAsset de la interfície IDAO, nos devolverá true y el test pasará. Para comprobar que esto es cierto, basta con cambiar el valor de retorno de la función de IDAO y veremos que el test no pasa.

En el ejemplo anterior, nada nos garantiza que realmente se haya llamado a la función de IDAO, ya que SaveAsset de AssetManager podria haber devuelto true directamente. Ahora vamos a ver como podemos "mockear" una función y verificar que realmente se llama:

[TestMethod]
public void GetAssetByName()
{
   
var mockDao = new Mock<IDAO>();
   
AssetManager assetManager = new AssetManager(mockDao.Object);

    assetManager.GetAssetByName("MyFirstAsset");

    mockDao.Verify(dao => dao.GetAssetByName("MyFirstAsset"));
}

Como podemos ver claramente en el código, con la función Verify verificamos que se haya llamado a la función GetAssetByName de la interficie IDAO con el parámetro MyFirstAsset. Podemos comprobar que esto es cierto modificando el string "MyFirstAsset" de una de las dos llamadas por otro string. El resultado será que el test no pasará. Este tipo de cosas puede hacer que nuestro test sea demasiado frágil y, por lo tanto, difícil de mantener. Moq nos ofrece la classe It para lidiar con este tipo de problemas. Podriamos substituir el string "MyFirstAsset" por sentencias del tipo:

  • It.IsAny<string>() -> pasa como parámetro cualquier string

  • It.Is<string>(s => s.StartsWith("My")) -> pasa como parámetro un string que empieza por "My"

  • It.IsRegex("\ba") -> pasa como parámetro un string que empieza por la letra a

Al igual que podemos comprobar que se ha llamado a una función, quizá también nos pueda interesar comprobar que se ha seteado una propiedad. Para hacerlo, nos apoyaremos en la función VerifySet del mock:

[TestMethod]
public void Verify_ConnectionString_was_set()
{
   
var mockDao = new Mock<IDAO>();

    AssetManager assetManager = new AssetManager(mockDao.Object);

    mockDao.VerifySet(x => x.ConnectionString = It.Is<string>(s => s.StartsWith("Non")));
}

Con este código comprobaremos que se ha seteado la propiedad ConnectionString con un valor que empieza por "Non".

Y por hoy ya tenemos suficiente. Hemos visto que es muy fácil utilizar Moq y hacer los primeros pasos con él. En posteriores tutoriales veremos más características de este framework.

Hasta la próxima!

miércoles, 26 de enero de 2011

La importancia de un buen Product Owner y un buen Product Backlog

product-ownerMuchas de las implantaciones de Scrum ( u otras metodologías ágiles ) que he conocido estos años son implantaciones que podríamos llamar bottom-up, es decir que parten del equipo de desarrollo. Estos se dan cuenta que no pueden continuar con la organización que llevan ahora y deciden tomar cartas en el asunto y empezar a hacerlo por ellos mismos. Es lo que se denomina comúnmente agilismo de guerrilla.

Aun siendo una muy buena opción para empezar ( yo empecé así ) a la larga se acaba quedando corta y es necesaria la implicación de la gerencia para llegar a algo más completo. Para mi los principales puntos débiles son:

  • Adolecen de un mentor experimentado: en la mayoría de los casos, el equipo se ha documentado sobre Scrum y empieza a probarlo.

  • Mala repartición de los roles: sobretodo si sólo está utilizando Scrum un equipo, hay gente que tiene dos roles: equipo y Scrum Master o equipo y Product Owner. La por situación es si hay alguien que tiene los tres roles, en lo que esto tiene muchos números de convertirse en un command and control encubierto.

  • Product Owner poco implicado: al ser un miembro del equipo le va a costar hacer de Product Owner. No va a tener relación directa con el cliente, no va a saber todo lo que se tiene que hacer a lo largo del tiempo o no le va a gustar definir bien las historias.

Veamos este punto con un poco más de detalle. Todas las cosas en contra que he comentado no tienen porqué pasar... pero tienen muchos números de que pasen. A los desarrolladores en general no nos gusta demasiado hacer especificaciones, definiciones de acabado y cosas por el estilo. Por lo menos a mi no me entusiasma ni a ninguno de mis compañeros. Esto desemboca en que nuestro Product Backlog no sea lo que tendría que ser.

Pero llega un día en que alguien con mucha más relación con el cliente y con visión del producto se instala en tu equipo. Y empieza a generar un Product Backlog con todas las historias que quiere que a corto/medio plazo se implementen, las prioriza, detalla más las más importantes, especifica las condiciones de aceptación de cada una de ellas. Este día será un día importante en tu historia dentro del proyecto. Los cambios más importante que se producirán en tu equipo para mi son:

  • Ánimo dentro del equipo: ver que la gerencia se preocupa por el proyecto y pone toda la carne en el asador para que tire adelante anima a la gente.

  • Mayor cuidado con la aplicación: todos somos profesionales y estamos comprometidos, pero no es lo mismo que cada quince días el equipo le haga a un Product Owner "externo" la demo del sprint que se la hagan entre ellos.

  • Mayor acierto con la implementación de las histórias: el equipo desarrollará lo que el Product Owner quiere, no lo que él cree que el Product Owner quiere.

  • Mayor visión del producto: el equipo sabe hacia donde tirará el proyecto y puede tomar decisiones en función de ello.

Por lo tanto, si tienes ya un buen Product Owner en tu equipo, cuídalo y no lo dejes marchar, y sinó búscate uno en quanto puedas!

 

Nota 1: este post está basado en hechos reales. Ningún Product Owner, Scrum Master o miembro del equipo ha sido maltratado en la realización del mismo.

Nota 2: este post está basado en mi experiencia. Si la tuya es diferente, no dejes de contarla en los comentarios!