لقد حاولت العثور على أمثلة حول كيفية استخدام علامة تركيبات جديدة مع pytest_django.
شيء مثل:
import pytest
from django.contrib.sites.models import Site
from django.contrib.auth.models import User
@pytest.fixture(scope="session", autouse=True)
@pytest.mark.django_db
def project_setup(*args, **kwargs):
user = User.objects.create(username="session user #1")
assert User.objects.count(), 1
site, created = Site.objects.get_or_create(id=1)
site.domain = "testserver"
site.save()
لإجراء بعض التعديلات على ديسيبل بعد أن يصبح اختبار ديسيبل جاهزًا.
فشل هذا مع الخطأ "فشل: الوصول إلى قاعدة البيانات غير مسموح به ، استخدم علامة" django_db "لتمكين"
هل يمكن لشخص ما أن يقدم مثالاً على كيفية إعداد أشياء إضافية بعد أن يصبح اختبار ديسيبل جاهزًا؟
من الواضح أن هذا يحتاج إلى توثيق أفضل بالأمثلة ، وسأحاول تحسين المستندات.
في غضون ذلك ، آمل أن يساعدك هذا:
1) يجب أن تستخدم التركيبات التي تتعامل مع تعديلات قاعدة البيانات النطاق الافتراضي لـ "الوظيفة" - ستتم إعادة تعيين قاعدة البيانات بعد كل اختبار.
2) يمكنك طلب تركيبات db الخاصة بك. عمليا هذا يعني:
@pytest.fixture(autouse=True)
def project_setup(db): # the db argument will make sure the database access is requested for this fixture
User.objects.create(username="foo")
قد يكون لديك شيء محدد في ذهنك ، لكني أريد فقط أن أقدم لك تحذيرًا: أنصح عمومًا بعدم طلب الوصول التلقائي إلى قاعدة البيانات لجميع اختباراتك. لن تكون قادرًا على قلب هذا لاحقًا! لن تتمكن ببساطة من كتابة اختبارات الوحدة التي لا تستخدم قاعدة البيانات. ستكون اختباراتك بطيئة! يميل إعداد الاختبار العالمي مثل هذا أيضًا إلى النمو بمرور الوقت - فهو يبطئ الاختبارات ويصبح من الصعب جدًا الحفاظ عليه على المدى الطويل.
(أعاني بشدة من هذا في مشروعي الحالي ، لدي مجموعة من الاختبارات "القديمة" التي تستخدم الإعداد العالمي ، وهي بطيئة حقًا وتتعطل طوال الوقت.)
لقد أخبرتك فقط بما لا يجب عليك فعله بعد. إليك ما يمكنك فعله بدلاً من ذلك. :-) سيكون الحل هو استخدام فتى المصنع للمساعدة في إنشاء أشياء للاختبارات. إنه يجعل من السهل الحصول على العناصر التي تحتاجها بالضبط لاختبار معين ، دون الحاجة إلى اللجوء إلى الإعداد العام. يساعد في جعل إعداد الاختبار المعقد واضحًا وسهلاً وفي نفس الوقت تجنب التركيبات العالمية.
أتمنى أن يساعدك هذا!
هل هذه هي أفضل طريقة لاختبار مشروع / تطبيق django مع إعدادات مختلفة؟
import pytest
from django.conf import settings
@pytest.fixture
def basic_settings():
settings... # change something in settings
@pytest.fixture
def other_settings():
settings... # change something in settings
def test_basic(basic_settings):
pass
def test_other(other_settings):
pass
هناك تركيبات الإعدادات التي يمكن استخدامها لاستعادة الإعدادات تلقائيًا:
@pytest.fixture
def basic_settings(settings):
settings.SOME_SETTING = 1234
# SOME_SETTING will be automatically restored
هذا يعمل فقط لبعض الإعدادات. بعض الإعدادات لها آثار جانبية لا يمكن التراجع عنها حقًا بسبب كيفية استخدامها داخل Django والتطبيقات الأخرى. مثال على ذلك هو INSTALLED_APPS - بمجرد تحميل التطبيقات ، لا توجد طريقة لتغييرها.
بناءً على الإعدادات التي تهدف إلى تغييرها - قد يعمل هذا أو لا يعمل ، ولكن هذه هي الطريقة التي يعمل بها Django.
لسوء الحظ ، لم يتم توثيق تركيبات الإعدادات بعد ، لقد فتحت رقم 36 حتى لا أنساها.
إذا كان ذلك في المستندات ، فسيؤمن الأشخاص ساعات من الفشل حتى يجدون هذه المشكلة هنا. :)
@pytest.fixture(autouse=True) # only works with function scope (default)
def project_setup(db): # the db argument will make sure the database access is requested for this fixture
User.objects.create(username="foo")
تضمين التغريدة
سيكون من الرائع أن يكون هذا المثال في الوثائق.
ربما يجب أن تكون هناك صفحة في التوثيق بها أمثلة / أنماط شائعة؟ أعتقد أن أمثلة مثل هذه مناسبة بشكل جيد.
سيكون طلب السحب الذي يضيف هذا المثال إلى المستندات أمرًا رائعًا!
هذا قديم جدًا ، لكن لدي مشكلة مماثلة ووجدت حلًا مناسبًا لي ، لذلك في حالة تعثر شخص آخر عبر هذا:
@pytest.fixture(autouse=True, scope='session')
def post_db_setup(_django_db_setup, _django_cursor_wrapper):
with _django_cursor_wrapper:
call_command('loaddata', *settings.STATIC_FIXTURES, interactive=False)
أدرك أن التركيبات ليست الطريقة المفضلة للقيام بالأشياء ، ولكن إذا كنت تحتاج _ حقًا_ إلى ملء قاعدة البيانات الخاصة بك ببعض القيم قبل إجراء أي من الاختبارات ... مرة واحدة فقط ، فهذا يعمل جيدًا. يتأكد من أن _django_db_setup
قد تم إنجازه وأنك تحصل على _django_cursor_wrapper
لتكتب إليه (أظن أن أي إنشاء نموذج سيعمل في هذا السياق ، لكن لم أجربه).
لديك نفس المشكلة بالضبط ، نوع من الإحباط. سيكون رائعًا إذا تم توثيق ذلك ، فمن النمط الشائع حقًا ملء قاعدة بيانات قبل إجراء الاختبارات ، وملفات التنظيف اللاحقة ، والمرفقات ، والسجلات ، وما إلى ذلك :)
الحل المحدث الحالي لـ pytest == 3.0.7 pytest-django == 3.1.2
@pytest.fixture(scope='session')
def populate_nodes(request, django_db_setup, django_db_blocker):
from project.app.models import Attachment
call_command('populate', verbosity=0, interactive=False)
files = list(Attachment.objects.all().values_list('file', flat=True))
django_db_blocker.unblock()
# Cleanup
def teardown():
for file_path in files:
path, ext = os.path.splitext(file_path)
for path in glob.glob(f'{path}*'):
os.unlink(path)
django_db_blocker.restore()
request.addfinalizer(teardown)
return request
mariocesar هل رأيت هذا المثال في المستندات؟
أقوم بإغلاق المشكلة في الوقت الحالي (كان من المفترض أن يتم إغلاقها عند إضافة هذا المثال). يرجى إعادة الفتح بتفاصيل إضافية أو فتح مشكلة أخرى إذا كان هذا يحتاج إلى مزيد من التوضيح أو التحسين!
التعليق الأكثر فائدة
هذا قديم جدًا ، لكن لدي مشكلة مماثلة ووجدت حلًا مناسبًا لي ، لذلك في حالة تعثر شخص آخر عبر هذا:
أدرك أن التركيبات ليست الطريقة المفضلة للقيام بالأشياء ، ولكن إذا كنت تحتاج _ حقًا_ إلى ملء قاعدة البيانات الخاصة بك ببعض القيم قبل إجراء أي من الاختبارات ... مرة واحدة فقط ، فهذا يعمل جيدًا. يتأكد من أن
_django_db_setup
قد تم إنجازه وأنك تحصل على_django_cursor_wrapper
لتكتب إليه (أظن أن أي إنشاء نموذج سيعمل في هذا السياق ، لكن لم أجربه).