Pytest-django: Comment autoriser l'accès à la base de données globalement sans utiliser les marques django_db ?

Créé le 20 sept. 2016  ·  8Commentaires  ·  Source: pytest-dev/pytest-django

J'ai du mal à convertir mes tests basés sur le testeur Django en pytest.
je m'attendrais à ce que mettre

import pytest
pytestmark = pytest.mark.django_db

dans le dernier module du stacktrace qui appartient à mon code (lib/frontend/decorators.py)
atténuerait cela, mais ce n'est pas le cas. Le mettre dans mes quatre modules sur le stacktrace n'a pas aidé non plus.

Existe-t-il un moyen d'autoriser globalement l'accès à la base de données dans 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.

Commentaire le plus utile

Eh bien, vous pouvez toujours créer un appareil à utilisation automatique, comme

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

dans ton concours

Tous les 8 commentaires

Eh bien, vous pouvez toujours créer un appareil à utilisation automatique, comme

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

dans ton concours

La réponse de @enkore est la voie à suivre. Je viens également d'ajouter une FAQ dans la documentation :

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

Un module que j'importe dans un test se connecte à la base de données au moment de l'importation. Comment activer l'accès à la base de données globalement de manière à ce qu'il soit déjà autorisé lors de la collecte de test ? Merci!

@Telofy avez-vous déjà résolu le problème du marquage des importations avec un accès à la base de données ? J'ai le même problème...

Désolé, mais la façon dont Django (et pytest-django) fonctionne n'est pas possible de manière fiable. La seule solution appropriée consiste simplement à ne pas effectuer de requêtes de base de données pendant l'importation. pytest-django est construit autour du système de luminaires pytests et il n'y a aucun moyen pour pytest-django de garantir que les luminaires sont exécutés avant les importations.

Voir mon commentaire ici pour une explication plus détaillée de ce problème :
https://github.com/pytest-dev/pytest-django/issues/499#issuecomment-322056315

Ce n'est pas dans mon budget de pouvoir ou de temps de simplement réécrire toute la plate-forme de l'entreprise pour éviter ces requêtes. Ma solution est un patch de singe super laid dans 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

J'utilise également ce décorateur (en conjonction avec @pytest.mark.django_db ) pour m'assurer ensuite que les tests ne s'exécutent pas sur la mauvaise base de données, car cela a été un peu compliqué à prédire :

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

Merci pour l'exemple @Telofy - c'est vraiment utile. J'aimerais aussi éviter de réécrire toute notre base de code !

Faire des requêtes de base de données au moment de l'importation ne conduit pas seulement à de mauvais pytests, cela va causer des problèmes dans d'autres parties qui seront difficiles à localiser. Vous allez passer un mauvais moment.

Vous n'avez pas à réécrire toute votre base de code, vous pouvez la contourner en utilisant des méthodes/propriétés paresseuses. Code qui n'établit pas de connexion tant que la valeur n'est pas demandée. De même, passer uniquement des ensembles de requêtes sans évaluer fonctionnera. Éviter des trucs comme compter, etc.

Cette page vous a été utile?
0 / 5 - 0 notes