Bonne journée!Je m'appelle Andrey Sobolev et aujourd'hui je vais vous dire comment nous avons préparé le hook .pre-commit sur notre projet.introduction
Pour commencer, quelques mots sur ce que sont les crochets en général et pourquoi ils peuvent être nécessaires. Git out of the box fournit un outil qui peut exécuter vos scripts lorsqu'un événement se produit (par exemple, pousser vers un serveur, etc.)Pre-commit est un complément pratique au hook de pré-validation git par défaut qui exécute les scripts décrits dans .pre-commit-config.yaml avant de valider. En théorie, cela semble simple, passons à la pratique.Installation
Définissez les dépendances nécessaires:pre-commit
autoflake
black
pyupgrade
reorder-python-imports
yesqa
flake8
flake8-annotations
flake8-annotations-coverage
flake8-bandit
flake8-broken-line
flake8-bugbear
flake8-builtins
flake8-commas
flake8-comprehensions
flake8-debugger
flake8-eradicate
flake8-executable
flake8-fixme
flake8-future-import
flake8-pyi
flake8-pytest
flake8-pytest-style
flake8-mutable
flake8-string-format
flake8-todo
flake8-unused-arguments
pytest
Je vais exprimer mon opinion sur flake-8 et linter en général. Si vous avez déjà un grand projet avec un tas de code hérité, vous pouvez supprimer en toute sécurité les linters. Les coûts qui seront dépensés pour "amener à l'idéal", les autorités ne l'apprécieront pas. Nous mettons des linters pour de nouveaux (et petits) projets. Je le répète, c'est mon opinion personnelle, je ne l'impose à personne.Intégration de l'environnement
Nous allons dans le répertoire racine de l'environnement de développement et exécutons les commandes suivantes$ pre-commit install
pre-commit installed at .git/hooks/pre-commit
$ pre-commit --version
pre-commit 2.4.0
Si .pre-commit jure sur sqlite, alors vous devrez l'installer (par exemple $ yum install sqlite) et reconstruire python
Configuration du fichier .pre-commit-config.yaml
Dans le répertoire racine de l'environnement, créez le fichier .pre-commit-config.yaml- repo: https://github.com/pre-commit/pre-commit-hooks
rev: "v2.5.0"
hooks:
- id: check-merge-conflict
- id: debug-statements
- repo: local
hooks:
- id: black
name: black
entry: black
language: system
types: [python]
args: [--line-length=200, --target-version=py37]
- id: autoflake
name: autoflake
entry: autoflake
language: system
types: [python]
args: [--in-place, --remove-all-unused-imports, --remove-duplicate-keys]
- id: pyupgrade
name: pyupgrade
entry: pyupgrade
language: system
types: [python]
args: [--py37-plus]
- id: reorder-python-imports
name: reorder-python-imports
entry: reorder-python-imports
language: system
types: [python]
args: [--py37-plus]
- id: yesqa
name: yesqa
entry: yesqa
language: system
types: [python]
- id: tests
name: Run tests
entry: "bash tests.sh"
language: system
verbose: true
Les tests
En plus de vérifier et de formater le code, nous effectuerons des tests au stade de la création du commit. Pour ce faire, nous utiliserons pytest (https://docs.pytest.org/en/latest/) et le configurerons selon nos besoins.Dans le répertoire racine de l'environnement, créez le dossier de tests et placez les fichiers suivantstest_example_without_db.py, test_example_with_db.pypour plus de commodité, configurez les tests afin que vous puissiez utiliser la base de données actuelle (par exemple, une copie de la base de données à partir du serveur de combat), et ne pas en créer de nouvelle à chaque fois .Test simple test_example_without_db.pydef inc(x):
return x + 1
def test_answer():
assert inc(3) == 4
Dans des tests simples, nous pouvons par exemple connecter le webbot et contourner les nœuds de notre système pour automatiser le travail manuel du testeur.Test à l'aide de la base de données test_example_with_db.pyimport pytest
from chat.models import ChatRoom
from settings import POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD, \
POSTGRES_HOST, POSTGRES_PORT
@pytest.fixture(scope='session')
def django_db_setup():
settings.DATABASES['default'] = {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': POSTGRES_DB,
'USER': POSTGRES_USER,
'PASSWORD': POSTGRES_PASSWORD,
'HOST': POSTGRES_HOST,
'PORT': POSTGRES_PORT,
}
@pytest.fixture
def db_access_without_rollback_and_truncate(request, django_db_setup, django_db_blocker):
django_db_blocker.unblock()
request.addfinalizer(django_db_blocker.restore)
def chat():
return ChatRoom.objects.all().count()
@pytest.mark.django_db
def test_chat():
assert chat() > 0
L'exemple est assez artificiel et créé exclusivement pour cette note, mais il nous permet néanmoins d'accéder à la base de données actuelle et d'effectuer des tests complexes qui vont au-delà des tests manuels.Nous incluons les tests dans .pre-commit
Pour connecter les tests, nous avons besoin d'un script shell dans le répertoire racine de l'environnement, que nous appellerons tests.sh:source ../../python38_env/bin/activate && python -m pytest -v tests
Son contenu est très évident, mais vous remarquerez peut-être que l'activation de l'environnement virtuel est explicitement écrite dans le code. Cela peut être gênant si votre équipe se développe sur différents postes de travail (par exemple, qui a déployé l'environnement sur une machine locale et que quelqu'un se développe sur un serveur).Vous pouvez résoudre ce problème via des variables dans l'exemple d' implémentation.env : github.com/Sobolev5/starlette-vue-backend/blob/master/.env.example (notez la variableENV_ACTIVATE ) github.com/Sobolev5/starlette-vue-backend /blob/master/tests.sh (analyser ENV_ACTIVATE et activer l'environnement)Créer un commit
Il reste maintenant à créer un commit et à voir comment cela fonctionne$ git add .
$ git commit -m Sobolev:TestPreCommitHook
Check for merge conflicts................................................Passed
Debug Statements (Python)................................................Passed
black....................................................................Failed
- hook id: black
- files were modified by this hook
reformatted /var/www/file.py
All done!
1 file reformatted, 2 files left unchanged.
autoflake................................................................Passed
pyupgrade................................................................Passed
reorder-python-imports...................................................Failed
- hook id: reorder-python-imports
- exit code: 1
- files were modified by this hook
Reordering imports in file.py
yesqa....................................................................Passed
Run tests................................................................Passed
- hook id: tests
- duration: 2.85s
tests/test_example_with_db.py::test_chat PASSED [ 66%]
tests/test_example_without_db.py::test_answer PASSED [100%]
Un commit est maintenant créé en deux étapes. À la première étape, les hooks formatent le code, donc après qu'ils fonctionnent, nous avons juste besoin de «répéter» les commandes.Il s'avère que la séquence suivante.$ git add .
$ git commit -m Sobolev:TestPreCommitHook
$ git add .
$ git commit -m Sobolev:TestPreCommitHook
C'est tout, merci de votre attention.Liens annexes
→ Liste complète des crochets