Lancer des tests unitaires avec Django
En tant que devops je dois mettre en place ce qu’il faut pour lancer
des tests unitaires et ce sur une application écrite en python
et utilisant le
framework Django
. Cela doit me permettre de faire tourner ces tests dans un
pipeline gitlab et d’avoir le rapport du taux de couverture de code en sortie.
Mais voila je ne veux pas installer postgresql dans ma VM Linux ! Donc voyons
comment utiliser docker
et docker-compose
.
Mise en place d’une application Django
Le plus simple est de suivre le tutoriel disponible en français sur le site de Django ↗
Mais non, voici le lien vers le repo ↗ contenant le résultat. Je me suis arrêté après la mise en place des tests unitaires.
git clone git@gitlab.com:Bob74/tuto-django-test-docker.git
Installations des outils sur mon linux
Il faut bien que dans votre vm vous ayez installé Docker ↗, python devant l’être deja. Vous pouvez créer un environnement virtuel avec pyenv.
Pour installer docker-compose
dans une fenêtre shell tapez les commandes
suivantes :
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-composesudo chmod +x /usr/local/bin/docker-composesudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-composedocker-compose --version
docker-compose version 1.29.2, build 5becea4c
Maintenant créons le Dockerfile
qui nous permettra de lancer les tests
unitaires. Pour cela on créé un fichier Dockerfile
à la racine du projet
contenant ces lignes:
FROM python:3.9-slimENV PYTHONUNBUFFERED=1COPY . /code/WORKDIR /codeRUN pip install -r requirements.txt
Vous remarquerez qu’il n’y a rien de bien compliqué. Le contenu du fichier requirements.txt
coverage==6.0.2Django==3.2.8psycopg2-binary==2.9.1
Maintenant passons à l’écriture du fichier docker-compose.yml
:
version: '3'
services: app: build: ./ command: bash -c "while !</dev/tcp/postgres/5432; do sleep 1; done; coverage run manage.py test polls --parallel=4 && coverage report" volumes: - "./reports/:/code/reports" depends_on: - postgres environment: POSTGRES_DB: db_mysite POSTGRES_USER: 'user_mysite' POSTGRES_PASSWORD: 'pass_mysite' DATABASE_URL: "postgresql://user_mysite:pass_mysite@postgres:5432/db_mysite"
postgres: restart: always image: postgres:10-alpine environment: POSTGRES_USER: user_mysite POSTGRES_PASSWORD: pass_mysite POSTGRES_DB: db_mysite
Quelques explications :
- La stack est composée de deux containers:
- un qui contient la bdd, postgres, initialisé avec les paramètres USER, PASSWORD et DB
- un autre, app, qui servira à lancer les tests avec l’image créé précédemment.
La commande lancée permet d’attendre que la bdd soit disponible pour
s’exécuter.Elle attend que le port 5432
soit up sur le container postgres
.
Une fois disponible, les tests sont lancés et le rapport de couverture de code est
généré.
Voyons comment lancer les tests:
docker-compose run app
Creating mysite_app_run ... doneCreating test database for alias 'default'...Cloning test database for alias 'default'...Cloning test database for alias 'default'...System check identified no issues (0 silenced)........----------------------------------------------------------------------Ran 7 tests in 0.097s
OKDestroying test database for alias 'default'...Destroying test database for alias 'default'...Destroying test database for alias 'default'...Name Stmts Miss Cover------------------------------------------------------manage.py 12 2 83%mysite/__init__.py 0 0 100%mysite/settings.py 19 0 100%mysite/urls.py 3 0 100%polls/__init__.py 0 0 100%polls/admin.py 3 0 100%polls/apps.py 4 0 100%polls/migrations/0001_initial.py 6 0 100%polls/migrations/__init__.py 0 0 100%polls/models.py 17 4 76%polls/tests.py 42 27 36%polls/urls.py 4 0 100%polls/views.py 26 9 65%------------------------------------------------------TOTAL 136 42 69%
Et oui rien de plus simple! Attention le container postgresql continuera de vivre sa VIE. Pour l’arrêter il suffit de taper la commande suivante :
docker-compose down
Si vous avez fait des modifications sur le Dockerfile il faudra relancer le build de celui-ci :
docker-compose build app
Intégrer les tests dans un pipeline gitelab
Il suffit d’écrire le fichier .gitlab-ci suivant en ayant au préalable stocker
stages: - test
services: - postgres:12.2-alpine
unit-test-job: image: python:3.9-slim stage: test variables: POSTGRES_DB: postgres POSTGRES_USER: 'user_mysite' POSTGRES_PASSWORD: 'pass_mysite' POSTGRES_HOST_AUTH_METHOD: trust DATABASE_URL: "postgresql://user_mysite:pass_mysite@postgres:5432/db_mysite" script: - pip install -r requirements.txt - coverage run manage.py test --configuration=Test --parallel=2 - coverage report - mkdir coverage-reports - coverage xml -o coverage-reports/coverage-report.xml
coverage: "/TOTAL.+ ([0-9]{1,3}%)/" artifacts: paths: - coverage-reports/coverage-report.xml expire_in: 1d
Quelques explications :
- On utilise un des services fournis par gitlab et en l’occurrence ici
une bdd postgresql. Gitlab met à disposition aussi des
services ↗
mysql
etredis
.
La suite on peut ajouter :
- un stage de lint un lançant un job
flake8
- un autre pour lancer un scan pour envoyer un rapport dans
sonarqube
- un autre pour générer un package et le stocker dans le
package registry
de gitlab.
Petite cerise sur le gâteau. Voici comment créer le badge affichant le coverage sur la page du projet.
Allez dans le menu Settings -> General -> Badges
Remplir comme indiqué ci dessous :