En esta segunda parte sobre POM voy a tratar una estrategia que implementé con muy buenos resultados en distintos proyectos y que me permitieron obtener un grado de flexibilidad bastante importante a la hora de realizar y mantener los casos de prueba.
Cómo mencioné en el post anterior POM intenta encapsular la interacción con la página a través de una abstracción que la representa. Sin embargo esto nos deja bastante atados a la estructura de la página y nos quita flexibilidad a la hora de trabajar, porque si o si, nuestro modelo es una representación de una única página. Esto es algo que no se puede evitar si se utiliza POM, pero si se puede alivianar o desestructurar un poco.
Para hacer esto lo primero que tenemos que preguntarnos es ¿Qué es una página web? Hay muchas respuestas posibles a esta pregunta dependiendo de cómo la encaremos, pero hay una que es muy sencilla, y también poco exacta, pero que nos sirve mucho a la hora de encarar un proyecto de automatización utilizando POM. Utilizando esta respuesta o definición podemos considerar a una página web como una colección de controles web. De esta forma podemos dividir nuestro modelado en distintas capas, por un lado tendremos el modelado de los controles posibles, textbox, combos, botones, radiobuttons, etc. Y encapsular dentro de ellos toda la lógica de cómo encontrar el control e interactuar para llevar adelante determinada acción. Así por ejemplo tendremos una clase de tipo botón que sabrá cómo localizarse a sí mismo en un página web determinada y a su vez expondrá un método HacerClick() que sabrá qué hacer cuando quien diseñe el caso de prueba determine que quiere realizar un click sobre él. Siguiendo esta lógica luego, en una segunda capa de modelado, crearemos una clase para representar una página web, pero la misma estará compuesta por controles. Por ejemplo si fuera un login típico, tendría dos controles de tipo textbox, uno para el usuario y otro para el password, un control de tipo botón para realizar el login y uno de tipo texto o etiqueta, donde puedan verse los errores que la página exponga, por ejemplo el cásico “Usuario o clave incorrecta”. De esta forma si exponemos los controles como parte de la interfaz de la clase, es decir, como propiedades accesibles desde fuera de ella, cualquier caso de prueba podrá interactuar con ellos de la manera que crea conveniente evitando así que tengamos que generar métodos para determinados comportamientos.
Lo expuesto anteriormente nos permite separar un poco el modelo de la prueba, complica la lógica del modelo, pero simplifica y flexibiliza la prueba porque ahora es el caso de prueba quien interactúa con el modelo de la forma que quiere y no siguiendo métodos preestablecidos que devuelven un valor determinado. Sin embargo esto se puede flexibilizar un poco más aún o mejor dicho independizar la forma de encontrar un control del código fuente del modelo. La idea es extraer el método de búsqueda del control y el valor por el cual buscaremos del código y dejarlo almacenado en otro lado. En mi caso suelo utilizar diccionarios xml de controles donde mediante un nombre “funcional”, amigable para el usuario, pueda obtener el método de búsqueda, por ejemplo xpath y el valor de dicho xpath. Así entonces un control recibirá un “Nombre funcional” y un diccionario en donde se encuentra dicho nombre, y con estos parámetros será capaz de encontrarse a sí mismo en una página web determinada y, si en un futuro este método y/o valor de búsqueda cambian, sólo hará falta actualizar el diccionario y el script debería seguir funcionando sin problemas, es decir que editando un archivo ajeno al código fuente mantenemos la funcionalidad.