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.
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
Comentários muito úteis
Bem, você sempre pode criar um acessório de uso automático, como
no seu conftest