Dia bom!Meu nome é Andrey Sobolev e hoje vou lhe contar como preparamos o gancho .prometer em nosso projeto.Introdução
Para começar, algumas palavras sobre o que são os ganchos em geral e por que eles podem ser necessários. O Git pronto para uso fornece uma ferramenta que pode executar seus scripts quando um evento ocorre (por exemplo, enviar para um servidor etc.) Apré-confirmação é um complemento conveniente para o gancho de pré-confirmação padrão do git que executa os scripts descritos em .pre-commit-config.yaml antes de confirmar. Em teoria, parece simples, vamos à prática.Instalação
Defina as dependências necessárias: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
Vou expressar minha opinião sobre o flake-8 e o linter em geral. Se você já possui um projeto grande com um monte de código legado, pode excluir com segurança linters. Os custos que serão gastos em "levar ao ideal", as autoridades não apreciarão. Colocamos linters para novos (e pequenos) projetos. Repito, esta é a minha opinião pessoal, não a imponho a ninguém.Integração com o ambiente
Vamos para o diretório raiz do ambiente de desenvolvimento e executamos os seguintes comandos$ pre-commit install
pre-commit installed at .git/hooks/pre-commit
$ pre-commit --version
pre-commit 2.4.0
Se .pre-commit jurar no sqlite, será necessário instalá-lo (por exemplo, $ yum install sqlite) e compilar o python novamente
Configurando o arquivo .pre-commit-config.yaml
No diretório raiz do ambiente, crie o arquivo .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
Testes
Além de verificar e formatar o código, executaremos testes no estágio de criação do commit. Para fazer isso, usaremos pytest (https://docs.pytest.org/en/latest/) e configurá-lo para nossas necessidades.No diretório raiz do ambiente, crie a pasta tests e coloque os seguintes arquivostest_example_without_db.py, test_example_with_db.py lápor conveniência, configure os testes para poder usar o banco de dados atual (por exemplo, uma cópia do banco de dados do servidor de batalha) e não criar um novo sempre .Teste simples test_example_without_db.pydef inc(x):
return x + 1
def test_answer():
assert inc(3) == 4
Em testes simples, podemos conectar, por exemplo, webbot e ignorar os nós do nosso sistema para automatizar o trabalho manual do testador.Teste usando o banco de dados 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
O exemplo é bastante artificial e criado exclusivamente para esta nota, mas, no entanto, permite acessar o banco de dados atual e realizar testes complexos que vão além do teste manual.Incluímos testes em .pre-commit
Para conectar os testes, precisamos de um script de shell no diretório raiz do ambiente, que chamaremos de tests.sh:source ../../python38_env/bin/activate && python -m pytest -v tests
Seu conteúdo é muito óbvio, mas você pode perceber que a ativação do ambiente virtual está explicitamente escrita no código. Isso pode ser inconveniente se sua equipe estiver desenvolvendo em diferentes estações de trabalho (por exemplo, quem implantou o ambiente em uma máquina local e alguém desenvolveu em um servidor).Você pode resolver esse problema por meio de variáveis noexemplo de implementação.env : github.com/Sobolev5/starlette-vue-backend/blob/master/.env.example (observe a variável ENV_ACTIVATE)github.com/Sobolev5/starlette-vue-backend /blob/master/tests.sh (analise ENV_ACTIVATE e ative o ambiente)Crie uma confirmação
Agora resta criar um commit e ver como ele funciona$ 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%]
Uma confirmação agora é criada em duas etapas. No primeiro estágio, os ganchos formatam o código; portanto, depois que eles funcionam, precisamos apenas "repetir" os comandos.Acontece a seguinte sequência.$ git add .
$ git commit -m Sobolev:TestPreCommitHook
$ git add .
$ git commit -m Sobolev:TestPreCommitHook
Só isso, obrigado pela atenção.Sitelinks
→ Lista completa de ganchos