Pytest-django: ¿Cómo permitir el acceso a la base de datos globalmente sin usar las marcas django_db?

Creado en 20 sept. 2016  ·  8Comentarios  ·  Fuente: pytest-dev/pytest-django

Estoy luchando para convertir mis pruebas basadas en Django Test Runner a pytest.
Esperaría que poner

import pytest
pytestmark = pytest.mark.django_db

en el último módulo de stacktrace que pertenece a mi código (lib/frontend/decorators.py)
mitigaría esto, pero no lo hizo. Ponerlo en mis cuatro módulos en stacktrace tampoco ayudó.

¿Hay alguna forma en que pueda permitir globalmente el acceso a la base de datos en 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.

Comentario más útil

Bueno, siempre puedes crear un accesorio de uso automático, como

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

en tu concurso

Todos 8 comentarios

Bueno, siempre puedes crear un accesorio de uso automático, como

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

en tu concurso

La respuesta de @enkore es el camino a seguir. Acabo de agregar una pregunta frecuente en la documentación también:

http://pytest-django.readthedocs.io/en/latest/faq.html#cómo-puedo-dar-acceso-a-la-base-de-datos-a-todas-mis-pruebas-sin-el-marcador-db-django-

Un módulo que estoy importando en una prueba se conecta a la base de datos en el momento de la importación. ¿Cómo habilito el acceso a la base de datos globalmente de modo que ya esté permitido durante la recopilación de prueba? ¡Gracias!

@Telofy , ¿alguna vez resolvió el problema de marcar importaciones con acceso a db? Tiene el mismo problema...

Lo sentimos, pero la forma en que funciona Django (y pytest-django) no es posible de manera confiable. La única solución adecuada es simplemente no realizar consultas a la base de datos durante el tiempo de importación. pytest-django se basa en el sistema de accesorios de pytests y no hay forma de que pytest-django pueda garantizar que los accesorios se ejecuten antes de las importaciones.

Vea mi comentario aquí para una explicación más detallada de este problema:
https://github.com/pytest-dev/pytest-django/issues/499#issuecomment-322056315

No está dentro de mi poder o presupuesto de tiempo simplemente reescribir toda la plataforma de la compañía para evitar esas consultas. Mi solución es un parche de mono súper feo en 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

También estoy usando este decorador (junto con @pytest.mark.django_db ) para asegurarme de que las pruebas no se ejecuten en la base de datos incorrecta, porque ha sido un poco complicado de predecir:

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

Gracias por el ejemplo @Telofy , eso es realmente útil. ¡También me gustaría evitar volver a escribir todo nuestro código base!

Hacer consultas de base de datos en el momento de la importación no solo conduce a pruebas de pytest incorrectas, sino que también causará problemas en otras partes que serán difíciles de rastrear. Lo vas a pasar mal.

No tiene que reescribir todo su código base, puede evitarlo usando métodos/propiedades perezosos. Código que no hace una conexión hasta que se le pide el valor. También funcionará pasar solo conjuntos de consultas sin evaluar. Evitar cosas como contar, etc.

¿Fue útil esta página
0 / 5 - 0 calificaciones