Ich habe Mühe, meine Django-Testläufer-basierten Tests in Pytest umzuwandeln.
Ich würde erwarten, dass das Setzen
import pytest
pytestmark = pytest.mark.django_db
in das letzte Modul des Stacktrace, das zu meinem Code gehört (lib/frontend/decorators.py)
würde dies mildern, tat es aber nicht. Es hat auch nicht geholfen, es in alle vier meiner Module auf dem Stacktrace zu stecken.
Gibt es eine Möglichkeit, den Datenbankzugriff in pytest-django global zuzulassen?
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.
Nun, Sie können jederzeit ein Autouse-Gerät erstellen, wie zum Beispiel
@pytest.fixture(autouse=True)
def enable_db_access(db):
pass
in deinem Wettbewerb
Die Antwort von @enkore ist der
http://pytest-django.readthedocs.io/en/latest/faq.html#how -can-i-give-database-access-to-all-my-tests-without-the-django-db-marker
Ein Modul, das ich in einem Test importiere, verbindet sich zum Zeitpunkt des Imports mit der DB. Wie aktiviere ich den DB-Zugriff global, sodass er bereits während der Testsammlung erlaubt ist? Danke!
@Telofy haben Sie jemals das Problem der Markierung von Importen mit DB-Zugriff gelöst? Habe das gleiche Problem...
Tut mir leid, aber die Art und Weise, wie Django (und pytest-django) funktioniert, ist nicht zuverlässig möglich. Die einzig richtige Lösung besteht darin, während des Imports keine Datenbankabfragen durchzuführen. pytest-django basiert auf dem Fixture-System von pytests und es gibt keine Möglichkeit, dass pytest-django sicherstellen kann, dass Fixtures vor dem Import ausgeführt werden.
Siehe meinen Kommentar hier für eine detailliertere Erklärung dieses Problems:
https://github.com/pytest-dev/pytest-django/issues/499#issuecomment -322056315
Es liegt weder in meiner Macht noch in meinem Zeitbudget, einfach die gesamte Plattform des Unternehmens neu zu schreiben, um diese Anfragen zu vermeiden. Meine Lösung ist super hässliches Affen-Patching in 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
Ich verwende diesen Dekorator auch (in Verbindung mit @pytest.mark.django_db
), um sicherzustellen, dass die Tests nicht in der falschen Datenbank ausgeführt werden, da die Vorhersage etwas kompliziert war:
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
Danke für das Beispiel @Telofy - das ist wirklich nützlich. Ich möchte auch vermeiden, unsere gesamte Codebasis neu zu schreiben!
Erstellen von db-Abfragen zum Importzeitpunkt führt nicht nur zu schlechten Pytests, sondern führt auch zu Problemen in anderen Teilen, die schwer aufzuspüren sind. Du wirst eine schlechte Zeit haben.
Sie müssen nicht Ihre gesamte Codebasis neu schreiben, Sie können es mit faulen Methoden/Eigenschaften umgehen. Code, der keine Verbindung herstellt, bis Sie nach dem Wert gefragt werden. Es funktioniert auch, nur Abfragemengen ohne Auswertung zu übergeben. Vermeiden Sie Dinge wie Zählen usw.
Hilfreichster Kommentar
Nun, Sie können jederzeit ein Autouse-Gerät erstellen, wie zum Beispiel
in deinem Wettbewerb