Taula de continguts

CI/CD amb Jenkins, Django i Selenium

En el context de DevOps, els sistemes de CI/CD han esdevingut molt importants per evitar-nos de fer tasques repetitives de testeig d'aplicacions que necessiten una revisió i actualització constant.

https://jenkins.io és probablement el software d'automatització de testeig més popular. El provarem juntament amb un projecte web fet amb Django (conegut com «the web framework for perfectionists with deadlines»), concretament el projecte de Borsa de Treball fet a l'institut Esteve Terradas de Cornellà.

Els tests funcionals que es realitzen en aquest projecte es duen a terme amb Selenium, unes llibreries disponibles en diferents llenguatges que ens permeten automatitzar les accions del browser com si es tractés d'un usuari real. Com que és extern al projecte en sí, es pot fer en un llenguatge diferent del propi projecte (pel nostre cas estan integrats en els tests de Django, però podrien fer-se ben bé a part).

, , , , , , , , , , , , ,

Servidor

Primer caldrà que disposem d'un servidor propi al núvol o en una VM a la màquina local. Preferentment ha de ser una VM Ubuntu 20.04 LTS, tot i que es pot fer amb qualsevol GNU/Linux.

També ho podeu instal·lar a la pròpia màquina local, però la idea d'aquest tutorial és poder instal·lar un servidor complert extern dedicat al testing.

Podeu crear la VM amb Vagrant amb el següent Vagrantfile:

Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/focal64"
  config.vm.hostname = "jenkinshost"
  # A casa fixem la IP per poder seguir treballant després
  # A l'insti vigileu de no col·lisionar les IP amb els vostres companys
  config.vm.network "public_network", ip: "192.168.1.221"
  # També podem accedir per localhost:8080  
  config.vm.network "forwarded_port", guest: 8080, host: 8080
  # Configurem mes paràmetres
  config.vm.provider "virtualbox" do |vb|
    vb.name = "jenkinshost"
    vb.gui = false
    vb.memory = "2048"
    vb.cpus = 2
  end
end


Instal·lar Jenkins

Per instal·lar Jenkins primer de tot ens cal disposar de Java:

$ sudo apt install default-jre

Després podeu seguir les instruccions estàndard de la web de Jenkins per a Debian/Ubuntu.

Si ja tenim instal·lat Jenkins, podem accedir-hi via port 8080. Recordeu obrir el firewall si esteu utilitzant algun proveïdor al núvol.

http://elmeuserver.com:8080

Us demanarà que li entreu un token d'admin que podreu trobar en un arxiu del sistema (així s'assegura que és un sysadmin el qui ho està instal·lant).

Selenium Web Driver

A més, per poder fer testing web funcional, ens caldrà disposar d'un browser, pel que instal·larem Firefox. Com que es tracta d'un servidor headless (sense GUI) no es podrà posar en marxa de forma gràfica, però Selenium disposa del model headless en el driver.

Si tens Ubuntu:

$ sudo apt install firefox firefox-geckodriver

Si utilitzes Debian has de descarregar el darrer geckodriver, descomprimir-lo i copiar-lo /bin, i instal·lar firefox-esr:

$ sudo apt install firefox-esr
$ wget https://github.com/mozilla/geckodriver/releases/download/v0.30.0/geckodriver-v0.30.0-linux64.tar.gz
$ tar xf geckodriver-v0.30.0-linux64.tar.gz
$ sudo cp geckodriver /bin


Projecte Django

Provarem els tests implementats al projecte de Borsa de Treball fet a l'institut Esteve Terradas de Cornellà.

Abans caldrà que configurem la base de dades i les dependències necessàries per treballar amb Python.

Si estàs en Ubuntu:

$ sudo apt install git python3-venv mysql-server

Si utilitzes Debian:

$ sudo apt install git python3-venv mariadb-server

Configurar la BD

Crearem una BD «borsa» que no farem servir però que el projecte necessita per no donar error. També crearem l'usuari «admin» amb permisos per accedir a totes les BD:

$ sudo mysql
mysql> create database borsa;
mysql> create user admin@localhost identified by "admin123";
mysql> grant all on *.* to admin@localhost;
mysql> flush privileges;

Provar projecte en Shell

Ara ja podem clonar el projecte de Borsa De Treball, seguint les pròpies instruccions del README.

Si tens Ubuntu:

$ sudo apt-get install -y libmysqlclient-dev python3-dev gdal-bin python3-mysql.connector python3-mysqldb libssl-dev libjpeg-dev

Si tens Debian:

$ sudo apt-get install -y libmariadb-dev-compat gcc gdal-bin libjpeg-dev python3-venv python3-dev

Descarreguem l'aplicació:

$ git clone https://github.com/aws2/BorsaDeTreball.git
$ cd BorsaDeTreball
$ python3 -m venv env
$ source env/bin/activate
(env)$ pip install -U pip
(env)$ pip install -r requirements.txt

Fins aquí les passes indicades al README. El prompt (env)$ ens indica que ara estem dins de l'entorn virtual «env».

Ara ens cal fer alguns ajustos per engegar el projecte. Primer de tot, necessitem un arxiu .env amb les variables d'entorn, però li traurem les 2 darreres línies on apareix la DATABASE_URL que cal ajustar:

(env)$ head -n -2 BorsaDeTreball/.env.example > BorsaDeTreball/.env
(env)$ echo "DATABASE_URL=mysqlgis://admin:admin123@localhost/borsa" >> BorsaDeTreball/.env

Ara fem uns checks abans de començar els tests:

(env)$ python manage.py check

Si no ha donat error, podem engengar els tests (ull, que pot arribar a trigar alguns minuts):

(env)$ python manage.py test
(env) vagrant@ubuntu:~/BorsaDeTreball$ python manage.py test
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
....
----------------------------------------------------------------------
Ran 4 tests in 240.708s

OK
Destroying test database for alias 'default'...

Quan el test està correcte s'ens mostra un punt «.», mentre que si és erroni ens apareix una «E» juntament amb el motiu de l'error.

Troubleshooting

Si us apareix algun d'aquests errors:

selenium.common.exceptions.WebDriverException: Message: Failed to decode response from marionette
selenium.common.exceptions.InvalidSessionIdException: Message: Tried to run command without establishing a connection
selenium.common.exceptions.NoSuchWindowException: Message: Browsing context has been discarded
selenium.common.exceptions.WebDriverException: Message: Failed to convert data to an object

En aquest article de Stackoverflow s'indica que augmentant la RAM de la màquina de test fins a 2GB soluciona el problema.

Si apareixen errors de desenvolupament (s'ha introduït un error a la branca dev), hauria de ser mes segur canviar a la branca de producció i provar de nou:

$ git chechout pro
$ python manage.py test

Provar tests amb GUI

Si vols provar els tests veient com Selenium realitza els clicks i accions sobre el navegador (Firefox), pots comentar el codi on es posa el WebDriver en mode headless, al menys el trobaràs a als arxius core/tests.py i borsApp/tests.py. Comentar-les amb un # per tal de desactivar el mode headless.

#firefoxOptions.set_headless()

Per poder fer aquest pas necessitareu una màquina amb GUI o bé disposar de, com a mínim el paquet xorg, i connectar-nos a la VM habilitant un túnel per les X-windows.

A la VM:

$ sudo apt install xorg
$ exit

Des de la màquina host:

$ ssh user@maquina -X

O si esteu utilitzant Vagrant:

$ vagrant ssh -- -X

Testejeu abans si podeu arrencar el firefox:

$ firefox

Això pot ser interessant per depurar alguns problemes i per curiositat de veure com funciona el WebDriver de Selenium.


Automatitzar Jenkins

Si ens funcionen els tests en la màquina via shell, ara podrem automatitzar la seva execució amb Jenkins.

Accedim a Jenkins via port 8080 i ens loguem amb l'usuari administrador que hem configurat durant la instal·lació:

http://elmeuserver.com:8080

El què farem ara serà automatitzar totes les tasques que acabem de fer, posant-les en una tasca de Jenkins. Les passes a realitzar son les següents:

Crear tasca

Crear «item nou» del tipus «freestyle»

python -m venv env
. env/bin/activate
pip install -U pip
pip install -r requirements.txt
head -n -3 BorsaDeTreball/.env.example > BorsaDeTreball/.env
echo "DATABASE_URL=mysqlgis://admin:admin123@localhost/borsa" >> BorsaDeTreball/.env
python manage.py test

Executar tasca

  1. Anar a Dashboard → Borsa de Treball → Construir ara
  2. Anar a build, pel primer cas serà el #1 → Console Output