Hola, soy Troy McClure, y quizá me recuerden de otras charlas como: “Más allá del botón derecho publicar” o “Azure Alerts: ¿Has probado a reiniciar?”.
En esta ocasion vengo a intentar contaros “¿Qué es selenium?”
Para ello, antes debemos entender qué es el functional testing.
El functional testing o pruebas funcionales son aquellas que están destinadas a asegurar que un Sistema informático, sea cual sea, hace lo que se espera de él y además, cumple con la especificación dada.
Dentro del functional testing hay diferentes fases o tareas, como podéis ver en el diagrama, como son la toma de requisitos, la definición de los casos de uso o la planificación y ejecución de los test.
Existen, según su tipología, diferentes tipos de test funcionales. Algunos de estos tipos son test:
De regresión, que permiten evitar que cualquier modificación introducida en vuestras aplicaciones provoque un bug previamente verificado en fases anteriores de testing.
De compatibilidad, que permiten asegurar que la aplicación funciona en diferentes entornos, navegadores…
De aceptación, que aunque se pueden considerer parte del functional testing, a menudo se separan en una categoría aparte.
Evidentemente, estas pruebas pueden ser ejecutadas manualmente, pero la gracia es que se ejecuten de forma automática, de manera que se puedan integrar como parte de un proceso de testing integral… ¿De qué está formado este proceso de testing?
Pues hay diferentes tipos de tests, según el grado de profundidad que se prueba.
Los más conocidos por nosotros los desarrolladores son los Unit test y los Integration Tests.
Unit test es aquel conjunto de test que está pensado para probar una sola pieza del sistema, sin interacción con otras piezas o servicios, a fin de asegurar que el funcionamiento es el esperado.
Integration test, por su lado, es aquel conjunto de test pensados para asegurar una interacción correcta entre dos o más piezas de la aplicación. Sirven, por ejemplo, para verificar que la aplicación funciona cuando consume servicios externos o remotos en vez de servicios mockeados.
Estos dos tipos de test son los más conocidos por los desarrolladores, pero en un Plan de test integral, a veces hay otro tipo de usuarios que son los encargados normalmente de llevar a cabo los test funcionales y de aceptación. Estos son, los QA o, incluso, el propio usuario final, que valida funcionalmente la aplicación y acepta la solución existente como válida según la especificación inicial.
Así que… tenemos estos dos tipos de usuarios…
Nosotros, los developers, solemos ver a los QA y a los usuarios como…
… un demonio.
Su único objetivo en la vida es fastidiarnos, encontrando errores o interpretando las definiciones del producto de una manera que nunca fue o nunca entendimos así.
Por contra, ellos, los QAs o el propio usuario final, tiende a ver a los developers…
… así. Como Ralph. “Yo me llamo Ralph!”
Para un QA, un developer es alguien que no tiene en cuenta las mil y una características con las que cuenta un sistema, un navegador, el negocio… Para ellos, normalmente no vemos el producto como un todo.
Nada más lejos de la realidad…
Así pues, ahora que sabemos qué es el Functional Testing, Podemos volver a la pregunta inicial. ¿Qué es Selenium?
Si antes hemos hablado de Test Funcionales, de ejecuciones automáticas y de un plan integral de test en vuestra aplicación, Selenium es una de las herramientas que podemos utilizar para conseguirlo.
Selenium es un motor de ejecución de pruebas funcionales WEB, que permite ejecutar tests funcionales sobre una o varias plataformas y navegadores a la vez, utilizando un mismo código de testing. Pero quizá, llegados a este punto, es mejor que os lo enseñe con un ejemplo…
Demostrar:
Selenium usando Katalon en Firefox.
Selenium usando Visual Studio con C# y .NET Core 2.1
Llegados a este punto, y dado que todo el mundo sabe qué es Docker…
Bueno, quizá no todo el mundo sabe que es docker. Veamos…
Formalmente, Docker es un sistema de despliegue de aplicaciones basado en contenedores.
Que qué es un contenedor…
Un contenedor de docker es un entorno de ejecución aislado que proporciona uno o más puntos de entrada y que permite ejecutar aplicaciones en sistemas host sin necesidad de tener instalado el software que se quiere ejecutar. Únicamente hace falta tener el motor de docker funcionando.
¿Y qué pasa cuando para que una solución funcione necesitamos varias aplicaciones funcionando a la vez?
Para eso existe, entre otros sistemas… (no voy a entrar a Kubernetes y otros orquestadores…), la composición mediante docker-compose.
Docker compose es una herramienta que utiliza docker para formar conjuntos de varios contenedores que se ejecutan a la vez pero cada uno en un subsistema distinto. Es útil, por ejemplo, cuando tu aplicación, que corre en .NET Core y un contenedor Windows, se tiene que comunicar con otro contenedor que tiene una base de datos MySQL, en su propio sistema Linux.
Mediante docker Compose, se pueden arrancar todos estos servicios a la vez, definir relaciones entre ellos, puntos de entrada…
¿Y todo esto a qué viene? Pues resulta que Selenium tiene dos versiones preparadas para trabajar sobre contenedores Docker.
Por un lado, las imágenes self-contained especificas por navegador.
Estas imágenes incluyen:
Selenium instalado (en linux)
Una instancia del navegador correspondiente (Firefox, Chrome…)
La ventaja de estas imágenes es que permiten solo levantar aquel navegador que necesitas, para así lanzar las pruebas funcionales de forma explícita para dicho navegador…
Pero hemos dicho que queremos hacerlo genérico e integrar todos los navegadores posibles en nuestro plan de pruebas integral, ¿no?
Para eso, nos conviene utilizar lo que se conoce como Selenium Hub.
Selenium Hub es un motor de Selenium al que se pueden suscribir N drivers de ejecución. De esta manera, registrando los motores de Firefox y Chrome, podemos ejecutar tests sobre cualquiera de estos motores atacando a un único punto de entrada.
Vamos a verlo.
Demostrar:
Levantar grid con Docker Compose
Ejecutar tests de firefox desde Selenium
Apagar grid
Ya terminamos…
Todo esto, debe poderse automatizar de alguna manera… y ahí es donde VSTS… digo… Azure DevOps entra en escena.
Desde Azure DevOps podemos configurar nuestros pipelines para levantar un grid de Selenium (Selenium Hub + Drivers), ejecutar las pruebas funcionales disponibles, recoger los resultados y eliminar el grid previamente levantado… sin pasar por servicios externos!
Vamos a verlo.
Demostrar:
Build definition en Azure DevOps
Release definition en Azure DevOps
Ejecutar Release definition.
Antes de terminar, quiero daros unas pocas advertencias acerca de toda esta solución que os planteo.
Los contenedores Selenium evolucionan constantemente, y cosas que hoy funcionan, mañana con una version más actual no tienen por qué funcionar.
Por otro lado, cuando trabajéis con proyectos .NET Framework, y dado que los steps de build y test deben ser ejecutados desde un agente Windows, actualmente no es posible levantar el grid de selenium directamente en el agente, que obligatoriamente tiene que ser Linux. Es necesario, por tanto, definir un endpoint donde levantar vuestro grid (por ejemplo vía AKS o ACS, ambos servicios de manejo de contenedores en Azure) y conectaros allí desde vuestro agente de release / build.
Y por ultimo, no cualquier agente hosted de linux sirve. Por algún motive que no tengo muy claro, el Linux Preview no funciona. Por lo que he leído, se trata de un problema de contexto de ejecución, que impide que la IP de entrada al contenedor sea visible desde el propio agente. Usad en su lugar el agente Ubuntu.