Pytest-django: Como permitir o acesso ao banco de dados globalmente sem usar marcas django_db?

Criado em 20 set. 2016  ·  8Comentários  ·  Fonte: pytest-dev/pytest-django

Estou lutando para converter meus testes baseados no executor de testes do Django para pytest.
Eu esperaria que colocar

import pytest
pytestmark = pytest.mark.django_db

no último módulo do stacktrace que pertence ao meu código (lib/frontend/decorators.py)
atenuaria isso, mas não o fez. Colocá-lo em todos os meus quatro módulos no stacktrace também não ajudou.

Existe alguma maneira de permitir globalmente o acesso ao banco de dados em pytest-django?

vagrant@vagrant-ubuntu-trusty-64:/vagrant$ pytest 
== test session starts ==
platform linux2 -- Python 2.7.6, pytest-3.0.2, py-1.4.31, pluggy-0.3.1
Django settings: patient.settings (from ini file)
rootdir: /vagrant, inifile: pytest.ini
plugins: django-3.0.0, pythonpath-0.7.1
collected 265 items / 2 errors 

[...]

_ ERROR collecting lib/tests/report/testfunc.py _
lib/tests/report/testfunc.py:6: in <module>
    from report.func import generate_report_filename
lib/report/func.py:29: in <module>
    from frontend import chart
lib/frontend/chart.py:294: in <module>
    @pytest.mark.django_db
lib/frontend/decorators.py:20: in decorator
    if Site.objects.get_current().id in (allowed_site_ids):
/usr/local/lib/python2.7/dist-packages/django/contrib/sites/models.py:60: in get_current
    return self._get_site_by_id(site_id)
/usr/local/lib/python2.7/dist-packages/django/contrib/sites/models.py:39: in _get_site_by_id
    site = self.get(pk=site_id)
/usr/local/lib/python2.7/dist-packages/django/db/models/manager.py:127: in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
/usr/local/lib/python2.7/dist-packages/django/db/models/query.py:328: in get
    num = len(clone)
/usr/local/lib/python2.7/dist-packages/django/db/models/query.py:144: in __len__
    self._fetch_all()
/usr/local/lib/python2.7/dist-packages/django/db/models/query.py:965: in _fetch_all
    self._result_cache = list(self.iterator())
/usr/local/lib/python2.7/dist-packages/django/db/models/query.py:238: in iterator
    results = compiler.execute_sql()
/usr/local/lib/python2.7/dist-packages/django/db/models/sql/compiler.py:838: in execute_sql
    cursor = self.connection.cursor()
/usr/local/lib/python2.7/dist-packages/django/db/backends/base/base.py:162: in cursor
    cursor = self.make_debug_cursor(self._cursor())
/usr/local/lib/python2.7/dist-packages/django/db/backends/base/base.py:135: in _cursor
    self.ensure_connection()
E   Failed: Database access not allowed, use the "django_db" mark to enable it.

Comentários muito úteis

Bem, você sempre pode criar um acessório de uso automático, como

@pytest.fixture(autouse=True)
def enable_db_access(db):
    pass

no seu conftest

Todos 8 comentários

Bem, você sempre pode criar um acessório de uso automático, como

@pytest.fixture(autouse=True)
def enable_db_access(db):
    pass

no seu conftest

A resposta de @enkore é o caminho a seguir. Acabei de adicionar um FAQ na documentação também:

http://pytest-django.readthedocs.io/en/latest/faq.html#how -can-i-give-database-access-to-all-my-tests-without-the-django-db-marker

Um módulo que estou importando em um teste se conecta ao banco de dados no momento da importação. Como habilito o acesso ao banco de dados globalmente de forma que já seja permitido durante a coleta de teste? Obrigado!

@Telofy você já resolveu o problema de marcar importações com acesso db? Tem o mesmo problema...

Desculpe, mas a maneira como o Django (e pytest-django) funciona não é possível de maneira confiável. A única solução adequada é simplesmente não fazer consultas ao banco de dados durante o tempo de importação. pytest-django é construído em torno do sistema de fixtures pytests e não há como pytest-django garantir que os fixtures sejam executados antes das importações.

Veja meu comentário aqui para uma explicação mais detalhada sobre esse problema:
https://github.com/pytest-dev/pytest-django/issues/499#issuecomment -322056315

Não está ao meu alcance ou orçamento de tempo apenas reescrever toda a plataforma da empresa para evitar essas consultas. Minha solução é um patch de macaco super feio em conftest.py:

from pytest_django.plugin import _blocking_manager
from django.db.backends.base.base import BaseDatabaseWrapper

_blocking_manager.unblock()
_blocking_manager._blocking_wrapper = BaseDatabaseWrapper.ensure_connection

Também estou usando este decorador (em conjunto com @pytest.mark.django_db ) para garantir que os testes não estejam sendo executados no banco de dados errado, pois tem sido um pouco complicado prever:

def assert_test_db(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        assert connection.settings_dict['NAME'] == 'test_kf_server', connection.settings_dict
        return func(*args, **kwargs)
    return wrapper

Obrigado pelo exemplo @Telofy - isso é realmente útil. Eu também gostaria de evitar reescrever toda a nossa base de código!

Fazer consultas de banco de dados no momento da importação não leva apenas a pytests ruins, mas também causará problemas em outras partes que serão difíceis de rastrear. Você vai passar mal.

Você não precisa reescrever toda a sua base de código, você pode contorná-la usando métodos/propriedades preguiçosos. Código que não faz conexão até que seja solicitado o valor. Também passar apenas conjuntos de consultas sem avaliar funcionará. Evitando coisas como contagem etc

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

ojake picture ojake  ·  6Comentários

tolomea picture tolomea  ·  6Comentários

ryankask picture ryankask  ·  5Comentários

asfaltboy picture asfaltboy  ·  5Comentários

aljosa picture aljosa  ·  8Comentários