Execución de probas automáticas con Docker, Jenkins e Selenium Grid

De MediaWiki
Ir a la navegación Ir a la búsqueda

Introdución

Docker

Podemos descargar o binario e instalar:

Ou en linux:

Jenkins

Instalación

Ou a través de repositorio vía Linux, podemos descargar a última release estable de Jenkins:

$ sudo docker pull jenkins/jenkins:lts

E lanzar un contenedor:

$ sudo docker run -p 8080:8080 -p 50000:50000 -v jenkins_home:/var/jenkins_home jenkins/jenkins:lts

Os párametros do comando:

-p : : puerto, se indica que el contenedor tendrá expuesto su puerto 8080 (derecha) y se enlazará con el puerto 8080 (izquierda). Es decir, sabiendo que vamos a levantar la aplicación Jenkins dentro del contenedor,
-v :: volumen, se indica que para el contenedor que estamos levantando, vamos a realizar la persistencia de la ruta indicada mediante el volumen cuyo nombre indicamos precedido de los dos puntos (:). Por tanto, todo lo que este contenedor albergue dentro de la ruta “/var/jenkins_home”, será almacenado en el volumen de docker con nome jenkins_home.

Para consultar a lista de volumes que están activos:

$ sudo docker volume ls

jenkins/jenkins:lts : Nome da imaxe da que queremos construir un contedor.

Construirase un contedor de Jenkins tras executar o comenado, visualizando o log da execución curante o proceso.

No íntre no que apaguemos o contedor o terminal pechará a tarefa e devolveranos ó prompt.

Na construcción de Jenkins amosarase unha chave codificada que utilizaremos a primeira vez para identificarnos en Jenkins. O recomendable a continuación será facer a xestión de usuarios, creando o usuario administrador para non ter que uesas ese contrasinal cifrado en vindeiros accesos. Accedemos a Jenkins introducindo no navegador o enderezo:

Uso

Trátase dun servidor de integración continúa que permite levar a cabo distintas tarefas de xeito automatizado.

Estas labores poden levarse a cabo de xeito “simple” mediante un proyecto de tipo Freestyle ou multiproxecto, ou mediante pipelines, opción que vai collendo máis forza.

Procuraremos xenerar unha contorna simple de probas para; con investigación poderedes construir en base a algo máis de investigación, proxectos máis robustos e complexos.

Así pois, crearemos un proxecto de tipo Freestyle, de xeito semellente a un Lego. Coas pezas que podemos ir seleccionando (os distintos plugins que Jenkins incorpora), podemos importar código desde un repositorio; lanzar un proxecto maven con certos parámetros; enviar un correo electrónico cos resultados ao finalizar a execución...

Selenoid

Implementación en Golang que permite despregar un sistema de contedores con Selenium no seu interior.Neste sistema podemos executar os nosos proxectos indicando as características do navegador que desexamos lanzar e enrutando axeitdamente o enderezo de execución; e permitirá ver en tempo real cómo se executan as instancias dos navegadores coas nosas probas, permitindo facer grabación de vídeo de configurarse.

Partimos dun fichero de configuración. Neste caso implementaremos o seguiente:

 1 browsers.json
 2 {
 3     "chrome": {
 4         "default": "91.0",
 5         "versions": {
 6             "91.0": {
 7                 "image": "selenoid/vnc:chrome_91.0",
 8                 "port": "4444",
 9                 "path": "/"
10             }
11         }
12     }
13 }

Nel indicamoslle a Selenoid que debe integrar un controlador (e navegador) de Chrome versión 91. Selenoid descarga o contedor indicado desde DockerHub e porao en marcha cando sexa necesario. A imaxe correspondente a este nevagador é:

  • selenoid/vnc:chrome_91.0


Docker Compose

Docker Compose. facilita traballar con múltiples contenedores de xeito simultáneo. Esta ferramenta permite definir un esquema de contedores describindoos nun ficheiro con formato YAML.

Existen varios formatos de ficheiros docker-compose.yml; usaremos neste exemplo a 3.9.

Para máis información pódése consultar a documentación oficial de Docker.

O noso ficheiro:

 1 docker-compose.yml
 2 version: "3.9"
 3 
 4 volumes:
 5         jenkins_home:
 6                 external:
 7                         name: jenkins_home  
 8 services:
 9         jenkins:
10                 build: ./jenkins_dockerfile/
11                 network_mode: bridge
12                 links:
13                   - selenoid
14                 volumes:
15                   - "jenkins_home:/var/jenkins_home"
16                 ports: ["9000:8080","50000:50000"]
17         selenoid:
18                 image: "aerokube/selenoid:latest-release"
19                 network_mode: bridge
20                 volumes:
21                   - "/var/run/docker.sock:/var/run/docker.sock"
22                   - "./config/:/etc/selenoid/:ro"
23                 ports: ["4444:4444"]
24         selenoid-ui:
25                 image: "aerokube/selenoid-ui"
26                 network_mode: bridge
27                 links:
28                   - selenoid
29                 ports: ["8080:8080"]
30                 command: ["--selenoid-uri", "http://selenoid:4444"]
E moi importante manter o indentado correctamente!

Nos campos raíz (sen indentar): volumes e “services”, sinálase a qué corresponde a árbore de datos que contén cada un.

volumes
onde se indica o nome do volumen de persistencia de datos que ímos utilizar xunto a os contenedores descritos máis abaixo. No noso escenario: jenkins_home
services
fai referencia os contenedores que ímos despregar ó executar este fichero de docker-compose.

Nesta caso serán:

  • jenkins
  • selenoid
  • selenoid-ui.

Os nomes só sirven para detectarse uns os outros mediante as referencias que podemos ver nos campos links e command. Neste último utilízase o nome para facer referencia o dominio na URL sen necesidad de coñecer la IP que dispondrá el contenedor a la hora de ser desplegado.

O apartado image hace referencia a la imagen que tomará el contenedor como base para ser desplegado. Aunque esto es obvio.

O campo network_mode indica a rede que vai a utilizar o contenedor en cuestión. En docker podemos crear tantas redes de comunicacións entre os distintos contedores como preciesemos; e facer que os contenedores sexan visibles (ou non) entre uns e outros. Para o noso obxectivo non precisamos crear ningún tipo de rede. Indicando o modo bridge facemos referencia a que todos van a estar dentro da rede por defecto.

No campo volumes informamos ó contenedor que debe usar a persistencia dos contedores que se indican. No caso de jenkins informase que debe usar o volumen jenkins_home (que declaramos ó inicio do documento), mentras que en selenoid indicamos as rutas que se van compartir entre o host (a nosa máquina local) e o propio contedor. Esto quere decir que aqueles ficheiros que situásemos na nosa ruta ./config/ serán visibles dentro do contedor de selenoid na ruta /etc/selenoid/; o :ro no caso de selenoid fai referencia a que o path ./config/ tómase como path de SÓ LECTURA (Read Only).

O campo ports expondrá o porto do contenedor (dereita) co porto local (esquerda). Porén, se escribimos “9000:8080”, quere dicir que o noso porto 9000 na máquina local será o mesmo que o 8080 do contedor. No caso de Jenkins se estamos expoñendo “9000:8080”, o ir no noso navegador a http://localhost:9000 é o mesmo que estando DENTRO do contedor ir a http://localhost:8080.

Finalmente, o campo build que podemos atopar no servizo de Jenkins fai que, en lugar de partir dunha imaxe base (como facemos nos casos de selenoid), partimos dun ficheiro Dockerfile (un fichero sen extensión e con nome Dockerfile), desde o que se construirá o contedor en cuestión de Jenkins.

Dockerfile

Este ficheiro utilízase para construir contedores con algún tipo de configuración da que non se dispón de serie.

Para o noso escenario queremos instalar Python e a súa ferrameenta Pip para poder utilizalas na execución do proxecto.

Para ello, a continuación lo describimos:

Dockerfile

FROM jenkins/jenkins:lts
USER root
RUN apt-get update && \
    apt-get -y install python3 && \
    apt-get -y install python3-pip && \
    pip3 install --no-cache-dir selenium && \

É un fichero cunha serie de comandos moi básicos. Para construir o contedor, a docker díselle:

FROM (a partir de la imagen) jenkins/jenkins:lts
USER (utilizando el usuario) root
RUN (ejecuta los siguientes comandos)
apt-get update
apt-get -y install python3
apt-get -y install python3-pip
pip3 install --no-cache-dir selenium

Estos serán executados durante a creación do contenedor. Dada a imaxe da que partimos, cando termine de construir o contenedor ponrase en marcha o servizo de Jenkins igual que se o fexieramos sen o uso do Dockerfile.

Execución

.
├── config
│   └── browsers.json
├── docker-compose.yml
└── jenkins_dockerfile
    └── Dockerfile

Canto temos listo todo e ubicado nos devanditos cartafois (as rutas que se indican dentro do fichero docker-compose.yml), levantaremos os contenedores mediante o comando:

$ sudo docker-compose up

Se desexamos ignorar o log podeamos utilizar o parámetro -d (detached) e a consola volvería estar disponible tras executar o comando.

Cos contedores en marcha, tras executar ó inicio o contedor de jenkins de xeito independente persistindo os datos mediante o volumen jenkins_home, podemos ver que nesta ocasión jenkins xa non nos pregunta pola configuración; aparece xa configurado e únicamente debemos crear o proxecto de probas.

Utilizaremos o Freestyle coma tipo de proyecto.

Importar código fonte

Una vez creado, agregamos a opción de importar código fuente mediante Git indicando o repositorio onde temos situado o ficheiro de probas (no noso escenario un ficheiro python cunha proba básica de navegación e comprobación da existencia dun texto nunha web). Se é un repositorio privado, pedirá as credenciais.

Execución

O noso ficheiro é un script en python, polo que únicamente necesitaríamos executar un comando na shell:

python3 PROBAselenium.py

Unha vez introducido gardamos o proxecto e, antes de executalo, abrimos unha nova ventana do navegador dirixíndonos a interfaz de Selenoid:

No dashboard, pulsamos Ejecutar proyecto en Jenkins e volvendo de novo a Selenoid vemos:

  • como se xenera unha nova sesión de Chrome en vivo.
  • tras acabar a proba, recibimos o resultado dentro do proxecto de Jenkins.

Proba selenium utilizada

 1 #PROBAselenium.py
 2 import unittest
 3 from selenium import webdriver
 4 from selenium.webdriver.common.by import By
 5 from selenium.webdriver.common.keys import Keys
 6 
 7 import time
 8 
 9 class prueba_selenium(unittest.TestCase):
10 
11     def setUp(self):        
12         print("Execútome antes de cada test")
13         #self.driver = webdriver.Chrome()
14         self.driver = webdriver.Remote(command_executor="http://selenoid:4444/wd/hub",
15                            desired_capabilities={'browserName': 'chrome', 'browserVersion':'91.0', 'selenoid:options':{'enableVNC':True}})
16 
17     def test_a(self):        
18         print("Execútome en cada test A")
19 
20         #GOOGLE
21         self.driver.get("https://www.google.com")
22         time.sleep(5)
23         #aceptamos cookies
24         self.driver.find_element(By.XPATH, "//div[text()='Acepto']/ancestor::button").click()
25         time.sleep(5)
26         #buscamos texto wikipedia                
27         search_bar = self.driver.find_element(By.NAME, "q")
28         time.sleep(5)
29         search_bar.send_keys("Wiki Cifp Rodolfo Ucha")
30         time.sleep(5)
31         search_bar.send_keys(Keys.ENTER)
32 
33         #BUSQUEDA DE GOOGLE
34         self.driver.find_element(By.XPATH, "(//div[@id='search']/descendant::div[@class='g'])[1]/descendant::a[1]").click()
35 
36         #WIKI DO CIPF RODOLFO UCHA
37         title = self.driver.title
38 
39         self.assertEqual("Páxina Principal - MediaWiki", title)
40         pass
41 
42     def tearDown(self):
43         print("Execútome despois de cada test")
44         self.driver.quit()
45         pass
46 
47 if __name__ == "__main__":
48     unittest.main()

Conclusións

Introdúxose someramente e con enfoque didáctico algunhas ferramentas que ofrecen moitas posibilidades na xestión do desenvolvemento de proxectos software; e, entre outras cousas, facilitan as probas de aceptación mediante probas automáticas.

Pódense ampliar coñecementos indagando sobre contedores docker, acoplamento de escravos Jenkins sobre os que executar as Build en Windows e Linux, probas con diferentes navegadores en Selenoid, activación do seu sistema de grabación de vídeo, ou ampliando as posibilidades de proba de Selenium, con Python ou Java.

Biografía