Guten Tag!Mein Name ist Andrey Sobolev und heute werde ich Ihnen erzählen, wie wir den Pre-Commit-Hook für unser Projekt vorbereitet haben.Einführung
Zunächst ein paar Worte darüber, was Haken im Allgemeinen sind und warum sie möglicherweise benötigt werden. Git out of the box bietet ein Tool, mit dem Sie Ihre Skripte ausführen können, wenn ein Ereignis auftritt (z. B. auf einen Server übertragen usw.).Pre-Commit ist ein praktisches Add-On zum Standard-Git-Pre-Commit-Hook, der die in beschriebenen Skripte ausführt .pre-commit-config.yaml vor dem Festschreiben. Theoretisch klingt es einfach, lassen Sie uns mit dem Üben fortfahren.Installation
Stellen Sie die erforderlichen Abhängigkeiten ein: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
Ich werde meine Meinung zu Flake-8 und Linter im Allgemeinen äußern. Wenn Sie bereits ein großes Projekt mit einer Reihe von Legacy-Code haben, können Sie Linters sicher löschen. Die Kosten, die für die "Idealisierung" aufgewendet werden, werden die Behörden nicht zu schätzen wissen. Wir setzen Linters für neue (und kleine) Projekte. Ich wiederhole, das ist meine persönliche Meinung, ich lege sie niemandem auf.Umgebungsintegration
Wir gehen in das Stammverzeichnis der Entwicklungsumgebung und führen die folgenden Befehle aus$ pre-commit install
pre-commit installed at .git/hooks/pre-commit
$ pre-commit --version
pre-commit 2.4.0
Wenn .pre-commit auf sqlite schwört, müssen Sie es installieren (z. B. $ yum install sqlite) und Python erneut kompilieren
Einrichten der Datei .pre-commit-config.yaml
Erstellen Sie im Stammverzeichnis der Umgebung die Datei .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
Tests
Zusätzlich zum Überprüfen und Formatieren des Codes führen wir Tests in der Phase der Erstellung des Commits durch. Dazu verwenden wir pytest (https://docs.pytest.org/en/latest/) und konfigurieren es für unsere Bedürfnisse.Erstellen Sie im Stammverzeichnis der Umgebung denTestordner und legen Sie die folgenden Dateien test_example_without_db.py, test_example_with_db.py dort ab. Konfigurieren Sie die Tests so, dass Sie die aktuelle Datenbank verwenden können (z. B. eine Kopie der Datenbank vom Battle Server), und erstellen Sie nicht jedes Mal eine neue .Einfacher Test test_example_without_db.pydef inc(x):
return x + 1
def test_answer():
assert inc(3) == 4
In einfachen Tests können wir zum Beispiel einen Webbot verbinden und die Knoten unseres Systems umgehen, um die manuelle Arbeit des Testers zu automatisieren.Testen Sie mit der Datenbank 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
Das Beispiel ist ziemlich künstlich und wurde exklusiv für diesen Hinweis erstellt. Es ermöglicht uns jedoch, auf die aktuelle Datenbank zuzugreifen und komplexe Tests durchzuführen, die über manuelle Tests hinausgehen.Wir schließen Tests in .pre-commit ein
Um die Tests zu verbinden, benötigen wir ein Shell-Skript im Stammverzeichnis der Umgebung, das wir tests.sh nennen:source ../../python38_env/bin/activate && python -m pytest -v tests
Der Inhalt ist sehr offensichtlich, aber Sie können feststellen, dass die Aktivierung der virtuellen Umgebung explizit im Code geschrieben ist. Dies kann unpraktisch sein, wenn Ihr Team auf verschiedenen Workstations entwickelt (z. B. wer die Umgebung auf einem lokalen Computer bereitgestellt hat und jemand auf einem Server entwickelt).Sie können dieses Problem durch Variablen im Implementierungsbeispiel .env lösen:github.com/Sobolev5/starlette-vue-backend/blob/master/.env.example (beachten Sie die Variable ENV_ACTIVATE)github.com/Sobolev5/starlette-vue-backend /blob/master/tests.sh ( ENV_ACTIVATE analysieren und Umgebung aktivieren)Erstellen Sie ein Commit
Jetzt bleibt ein Commit zu erstellen und zu sehen, wie es funktioniert$ 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%]
Ein Commit wird jetzt in zwei Schritten erstellt. In der ersten Phase formatieren Hooks den Code. Nachdem sie funktionieren, müssen wir nur die Befehle „wiederholen“.Es stellt sich die folgende Reihenfolge heraus.$ git add .
$ git commit -m Sobolev:TestPreCommitHook
$ git add .
$ git commit -m Sobolev:TestPreCommitHook
Das ist alles, danke für Ihre Aufmerksamkeit.Sitelinks
→ Vollständige Liste der Haken