[PYTHON] Exécutez flake8 et pytest sur GitLab CI

Que traiter dans cet article

--Exécuter flake8 et pytest dans le pipeline GitLab --Modifier le calendrier d'exécution ci-dessus lors de la soumission d'une demande de fusion

Comment avez-vous écrit cet article?

Je sais que l'analyse statique, l'utilisation de formateurs et l'écriture de code de test sont utiles pour garantir la qualité du logiciel, mais il est difficile (ou simplement) de l'introduire dans le développement d'équipe. Je me demandais quoi faire).

Comme j'utilise GitLab dans mon travail quotidien, j'ai pensé qu'il serait possible de créer rapidement un mécanisme simple, en dehors des choses difficiles, alors je l'ai résumé brièvement.

Tant que vous vous inscrivez à GitLab, vous pouvez l'exécuter avec le plan gratuit, vous pouvez donc l'essayer tout de suite.

Environnement d'exécution

--GitLab.com (service cloud)

1. Construction de l'environnement et contrôle Flake8

1-1. Créer un référentiel dans GitLab

Créez un référentiel dans GitLab pour effectuer une série de tâches. C'est privé et d'accord.

1-2. Ajout de gitlab-yml et PUSH

C'est extrêmement simple sans le concept de division de scène. Tirez l'image de Python3 et exécutez flake8 avec le code suivant dans le répertoire src.

image: python:3
 
before_script:
  - pip install flake8
 
test:
  script:
    - flake8 src/

Lorsque j'ai vérifié CI / CD après PUSH, j'ai pu confirmer que le pipeline fonctionnait et que l'analyse par flake8 était en cours.

2. Ajouter un test

Maintenant que nous avons fini d'exécuter flake8, exécutons un test avec pytest.

2-1. Création et exécution de tests localement

Créons un code de test avec une structure de répertoires qui sépare les fichiers de test comme indiqué ci-dessous.

.
├── __init__.py
├── poetry.lock
├── pyproject.toml
├── src
│   └── main.py
│   └── __init__.py
├── tests #ajouter à
│   └── test_main.py #ajouter à
│   └── __init__.py #ajouter à
└── venv

Le contenu du code de test est le suivant. Je ne me soucie pas vraiment du contenu cette fois, donc c'est tout à fait approprié.

import sys, os
current_path = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, current_path + '/../')

from src import main

def test_add():
    result = main.add(3, 5)
    expected = 8

    assert result == expected

def test_substract():
    result = main.substract(10, 5)
    expected = 5

    assert result == expected

def test_multiply():
    result = main.multiply(4, 5)
    expected = 20

    assert result == expected

J'ai exécuté le test créé localement et j'ai confirmé que tout était passé.

$ pytest tests   
======================== test session starts ========================
platform darwin -- Python 3.7.6, pytest-5.3.2, py-1.8.1, pluggy-0.13.1
collected 3 items                                                   

tests/test_main.py ...                                        [100%]

========================= 3 passed in 0.01s =========================

2-2. Mesure de la couverture

J'essaierai également de mesurer la couverture en utilisant pytest-cov.

$ pytest --cov=src tests/  
======================== test session starts ========================
...
collected 3 items                                                   

tests/test_main.py ...                                        [100%]

---------- coverage: platform darwin, python 3.7.6-final-0 -----------
Name              Stmts   Miss  Cover
-------------------------------------
src/__init__.py       0      0   100%
src/main.py           6      0   100%
-------------------------------------
TOTAL                 6      0   100%


========================= 3 passed in 0.03s =========================

C'est ennuyeux, je vais donc ajouter un nouveau code à main.py pour réduire délibérément la couverture.

...
def divide(x, y):
    return x / y

--Pytest -cov résultat de la sortie

% pytest --cov=src tests/   
============================================ test session starts ============================================
...
collected 3 items                                                                                           

tests/test_main.py ...                                                                                [100%]

---------- coverage: platform darwin, python 3.7.6-final-0 -----------
Name              Stmts   Miss  Cover
-------------------------------------
src/__init__.py       0      0   100%
src/main.py           8      1    88%
-------------------------------------
TOTAL                 8      1    88%


============================================= 3 passed in 0.03s =============================================

2-3. Exécution sur GitLab CI / CD

Ajoutez une nouvelle exécution de pytest-cov au fichier yaml et poussez-la.

image: python:3
 
before_script:
  - pip install flake8 pytest pytest-cov
 
test:
  script:
    - flake8 src/
    - pytest --cov=src tests/

Lorsque j'ai poussé le code et vérifié le résultat de l'exécution du pipeline, le pipeline s'est arrêté car le code nouvellement ajouté a été capturé par la vérification par flake8 comme suit.

Modifiez à nouveau le code et appuyez sur.

Cette fois, cela s'est terminé normalement.

2-4. Ajout de l'affichage de la couverture au pipeline

Même si vous mesurez la couverture, vous devez accéder au journal des emplois un par un, donc Cela correspond à afficher la couverture à l'aide de la fonction de GitLab.

Plus précisément, utilisez la fonction d'analyse de la couverture de test de la page des paramètres GitLab. Cela semble être une fonction pour afficher le taux de couverture du journal en utilisant une expression régulière, mais dans le cas de pytest-cov, c'est dans l'exemple, alors copiez-le et enregistrez-le tel quel.

Lorsque j'ai à nouveau appuyé sur le code, j'ai pu confirmer que le taux de couverture était affiché comme indiqué ci-dessous.

3. Modifier la synchronisation d'exécution du pipeline

À l'heure actuelle, le flux est PUSH → exécution du pipeline directement vers le maître, Dans le développement réel, je pense que les revues sont souvent incluses dans les demandes de fusion.

Donc, je voudrais exécuter le pipeline lors de la soumission d'une demande de fusion et créer un flux d'examen et de fusion uniquement si l'analyse par flake8 et le test par pytest réussissent.

3-1. Modification de yaml

Coupez une nouvelle branche et modifiez le contenu du fichier yaml comme suit. Le seul correctif est de spécifier merge_request avec uniquement.

Pour plus de détails, reportez-vous à ce qui suit à partir de la page GitLab. Pipelines for Merge Requests

image: python:3
 
before_script:
  - pip install flake8 pytest pytest-cov
 
test:
  script:
    - flake8 src/
    - pytest --cov=src tests/
  only:
  - merge_requests

Après avoir poussé, assurez-vous d'abord que le pipeline ne fonctionne pas comme avant.

3-2. Exécution de la demande de fusion

Soumettez une demande de fusion de la branche nouvellement coupée à master.

Après avoir soumis la demande de fusion (dans le pipeline)

Il a été confirmé que le pipeline fonctionne comme suit. Vous verrez un bouton appelé «Fusionner lorsque le pipeline réussit» qui n'est normalement pas affiché.

Après avoir soumis la demande de fusion (une fois le pipeline en fonctionnement)

L'affichage change à partir du moment où le pipeline est en cours d'exécution et le résultat de l'exécution (succès) et la couverture du pipeline sont affichés.

3-3. Exécution de la demande de fusion (échec)

Essayez de pousser un nouveau commit en ajoutant un cas de test qui échoue intentionnellement. Comme indiqué ci-dessous, il a été confirmé que le pipeline fonctionne non seulement pour les nouvelles demandes de fusion, mais également pour les validations supplémentaires.

Une fois le pipeline mis en service, l'affichage a été modifié comme suit. Avec les paramètres actuels (par défaut), la fusion est possible même si le pipeline échoue.

GitLab semble être en mesure de définir que la fusion n'est possible que lorsque le pipeline est réussi, donc Cochez «Les pipelines doivent réussir» pour enregistrer les paramètres.

Ensuite, comme indiqué ci-dessous, la fusion est devenue impossible. Je pense que cela dépend du projet comment le faire fonctionner, mais il serait plus facile de garantir la qualité s'il y avait une règle selon laquelle seul le code qui a passé l'analyse et les tests statiques sera fusionné.

Recommended Posts

Exécutez flake8 et pytest sur GitLab CI
Exécutez py.test sur Windows Anaconda et MinGW
Installez et exécutez Dropbox sur Ubuntu 20.04
Installez et exécutez Python3.5 + NumPy + SciPy sur Windows 10
Exécutez OpenVino sur macOS et environnement pyenv et pipenv
Exécutez l'application flask sur Cloud 9 et Apache Httpd
Installez Apache 2.4 sur Ubuntu 19.10 Eoan Ermine et exécutez CGI
Installez Docker sur Arch Linux et exécutez-le à distance
Exécutez Django sur PythonAnywhere
Exécutez mysqlclient sur Lambda
Exécutez OpenMVG sur Mac
Jusqu'à ce que l'ingénieur d'infrastructure crée GitLab pour exécuter CI / CD