Pytest-django: تحميل تركيبات سهلة

تم إنشاؤها على ٢٦ يونيو ٢٠١٢  ·  10تعليقات  ·  مصدر: pytest-dev/pytest-django

لقد لاحظت أنه تمت إزالة الوظيفة المساعدة لتحميل التركيبات. ربما لم يكن الأمر يستحق الإبقاء على ما هو عليه ، لكنني كنت أتساءل عما إذا كان هناك مجال لشيء أكثر فائدة.

سيكون أبسط شيء هو الوظيفة التي تأخذ قائمة بالتركيبات وتحملها. ما سيكون أفضل هو أن تكون قادرًا على استخدام متغير التركيبات داخل الفصل وتحميله تلقائيًا كما هو الحال مع حقائب اختبار Django.

يبدو الأمر وكأنه خطوة إلى الوراء قليلاً عن وظيفة Django المضمنة في الاختبار أن تفعل هذا:

    def setup_class(self):
        fixtures = ['base.json', 'things.json']

        for fixture in fixtures:
            call_command('loaddata', fixture)

.. حتى لو كان مجرد بضعة أسطر من التعليمات البرمجية.

ما رأيك؟

التعليق الأكثر فائدة

هذا يعمل. من https://flowfx.de/blog/populate-your-django-test-database-with-pytest-fixture/ :

import pytest

from django.core.management import call_command

@pytest.fixture(scope='session')
def django_db_setup(django_db_setup, django_db_blocker):
    with django_db_blocker.unblock():
        call_command('loaddata', 'potatoes_data.json')
# tests/test_models.py

def test_my_potatoes(db, django_db_setup):
    # GIVEN a full database of potatoes, as provided by the django_db_setup fixture
    all_my_potatoes = Potato.objects.all()

ال 10 كومينتر

السبب الرئيسي لإزالته هو أنني أعتقد أنه يجب عدم تشجيع استخدام التركيبات بشكل عام. راجع Carl Meyers (مطور Django core) يتحدث Pycon عن السبب (ابدأ المشاهدة في الساعة 16:25): http://www.youtube.com/watch؟v=ickNQcNXiS4&feature=player_detailpage#t = 986s

إذا كنت ترغب في استخدام التركيبات على الرغم من عيوبها ، فإن خياراتك هي:

1) افعل شيئًا مثل ما ورد أعلاه
2) قم بإنشاء دالة / علامة مساعدة في Conftest.py لمشروعك (يجب أن يكون فقط سطرين يستدعيان call_command)
3) استخدم فئة فرعية من Django TestCase مع سمة المباريات كالمعتاد

تقوم أدوات اختبار Django ببعض الاختيارات السيئة للاختبار (التجهيزات واحدة). أعتقد أننا يجب أن نشجع أفضل الممارسات حيثما كانت لدينا فرصة لتشجيع ممارسات الاختبار الأفضل. من الواضح أن ما هو أفضل ممارسة وما هو غير موضوعي ، ولكن نظرًا لأنه لا يزال من السهل حقًا استخدام التركيبات على أي حال ، لا أعتقد أنه من السيئ عدم الحصول على أي دعم في pytest-django.

لقد استخدمت شخصيًا مصانع الكائنات (غالبًا مع factory_boy) بدلاً من التركيبات في مشاريعي الخاصة بنجاح كبير حتى الآن. أود حقًا إنشاء صفحة توثيق "أفضل الممارسات" مع أمثلة ، سيكون هذا موضوعًا مثاليًا هناك.

أفكار؟

إذا تم إعادة تقديم التركيبات ، فمن المحتمل أن تكون علامة. كما يقول pelme ، يجب أن يكون هذا مجرد بضعة أسطر.

أنا شخصياً أقوم بإنشاء العناصر التي أحتاجها يدويًا داخل الاختبار ، على سبيل المثال: models.User(foo=bar) التي وجدتها أوضح حتى الآن. إذا وجدت نفسك تقوم ببناء نفس النموذج في عدد من الاختبارات ، يمكنك بسهولة إنشاء funcarg:

def pytest_funcarg__myuser(request):
    return models.User(foo=bar)

def test_foo(myuser):
    assert myuser.foo == bar

أخيرًا ، سأقوم أيضًا بتوصيل المشكلة رقم 11 التي تقترح funcarg "نماذج" مما قد يجعل هذا النمط من إنشاء العناصر في قاعدة البيانات أسهل.

لقد أدركت للتو أن funcarg الخاص بك ليس الأكثر سهولة في الاستخدام مع تغييرات طلب السحب في رقم 12. إذا تم تحميل funcarg الخاص بك قبل أن تتم تهيئة قاعدة البيانات فسوف تفشل. هذا هو السبب الذي يجعل admin_client funcarg يحتاج إلى استدعاء django_compat.setup_databases () والذي يمكنك أيضًا الاتصال به. لكنها ليست مثالية.

مرة أخرى ، هذا شيء يحله دمج funcarg / item مؤخرًا حيث يمكنك بعد ذلك فقط طلب funcarg "djangodb" وسيتم إعداده.

أقوم بإغلاق هذه المشكلة ، فقط لأكون واضحًا ، لا يزال من الممكن استخدام الفئات الفرعية TestCase من Django لاستخدام تحميل تركيبات Django مباشرة في فصول الاختبار.

لا تدعو أفضل الممارسات الحالية إلى تحميل تركيبات من الملفات ، لذلك لن يتم دعمها في pytest-django.

هذا يعمل. من https://flowfx.de/blog/populate-your-django-test-database-with-pytest-fixture/ :

import pytest

from django.core.management import call_command

@pytest.fixture(scope='session')
def django_db_setup(django_db_setup, django_db_blocker):
    with django_db_blocker.unblock():
        call_command('loaddata', 'potatoes_data.json')
# tests/test_models.py

def test_my_potatoes(db, django_db_setup):
    # GIVEN a full database of potatoes, as provided by the django_db_setup fixture
    all_my_potatoes = Potato.objects.all()

لا تدعو أفضل الممارسات الحالية إلى تحميل تركيبات من الملفات ، لذلك لن يتم دعمها في pytest-django.

الخيارات لهذا ، AFAIU ، تشمل:

  • تحميل تركيبات مثل JSON و / أو YAML حسب الحاجة

    • أصلا بدعم من الإطار

  • إنشاء كود مصدر Python
  • محاولة تعديل عمليات تفريغ SQL عندما تؤثر عمليات الترحيل على المخطط الأساسي

    • مضيعة للوقت دون داع (للمطور)

    • أسرع قليلاً من تركيبات JSON / YAML (في كل تشغيل اختباري)

بالنسبة لعدد كبير من السجلات ، تبدو التركيبات طريقة مقبولة تمامًا لتحميل بيانات الاختبار في قاعدة البيانات في Django. AFAIU ، لا توجد خطة لإيقاف تركيبات قاعدة بيانات Django إما بسبب الإهمال أو بسبب أي توصيات بشأن أفضل الممارسات.

أعتقد أنه عندما نتحدث عن أفضل الممارسات ، يجب أن يكون لدينا سياق الممارسة.

في موقع التدريج ، من الممكن أن تكون التركيبات الموصوفة مثبتة مسبقًا من الأجيال السابقة. بينما ، قد لا يكون هذا هو الحال في بعض الأحيان عند التطوير محليًا ، أو إذا كنت ترغب في اختبار قاعدة بيانات من البداية.

المشكلة التي يطرحها هذا الأمر هي عندما يحتوي التطبيق على الكثير من التطبيقات المختلفة ، والتي لديها حسابات مخصصة على القيم المخزنة في قاعدة البيانات من أجل تقديمها إلى المستخدم.

في حالة الاستخدام هذه ، قد تكون هناك بيانات في الواجهة الخلفية تقود هذه الحسابات ، وبينما أوافق تمامًا ، إذا كنت بحاجة إلى مستخدم فقط ، فقم فقط بإنشاء مستخدم وهذا كل شيء. لماذا أحتاج إلى حساب النهاية في هذه الحالة؟ حسنًا ، أنت لا تفعل ذلك. ومع ذلك ، في الحالات التي يتم فيها إنشاء اختبارات تضمن صحة حسابات النهاية الخلفية ، يجب أن أقوم بتثبيت كل عنصر أحتاجه كمثبت ، بينما يقوم Django بتثبيتها إذا تم وضعها في فصل دراسي كما هو متوقع مع جناح اختبار django. ضع في اعتبارك أن هناك حالات استخدام لإعادة الشراء الخاصة بك تتجاوز مشاريعك الشخصية :)

يجب تطبيق أفضل الممارسات على نطاق واسع وبطريقة عامة. أعتقد أن توخي الحذر والحذر من الإفراط في تطبيق الفلسفة ، وإلا فقد بعض وسائل الأتمتة التي ترضيها كتابة الكود.

نعم ، يمكن أن يكون هناك فئات قاعدة / خلط TestCase مع ، على سبيل المثال ، فئة مجموعة التركيبات التي تكون افتراضية إلى لا شيء أو قائمة ثوابت التكوين مثل ALL ، أو على سبيل المثال USER.

class TestCase:
    fixtures = None
    fixtures = ALL
    fixtures = USER
    fixtures = [,]
fixtures = ['book', 'author', 'etc...']
@pytest.fixture(autouse=True)
def django_fixtures_setup(django_db_setup, django_db_blocker):
    with django_db_blocker.unblock():
        call_command('loaddata', *['{}{}'.format(fixture, '.json') for fixture in fixtures])

أعلاه يعمل بشكل جيد أيضا بالرغم من ذلك

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات