Pytest-django: pytest.mark.django_db لا يلعب بشكل جيد مع setup_module ()

تم إنشاؤها على ١٤ سبتمبر ٢٠١٣  ·  15تعليقات  ·  مصدر: pytest-dev/pytest-django

هذا هو كود الاختبار الخاص بي:

import pytest
pytestmark = pytest.mark.django_db

from handy.db import do_sql, fetch_val

def setup_module(fetch_val):
    print 1
    do_sql('''
        create table test (
            id int primary key,
            tag int not null
        );

        insert into test values (1, 10), (2, 20);
    ''')
    print 2

def test_fetch_val():
    print 3
    assert fetch_val('select min(id) from test') == 1

وأحصل على DatabaseError: relation "test" does not exist من test_fetch_val() . أنا أيضا أحصل

2
Creating test database for alias 'default'...
3

الإخراج الملتقط. يبدو أنه تم استدعاء setup_module() قبل إنشاء قاعدة البيانات.

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

+1 بالنسبة لي ، مجرد التبديل من بعض اختبارات وحدة Djano الأولية ، يعد هذا عيبًا كبيرًا ، عند تهيئة قاعدة البيانات لحالات اختبار API الخاصة بي. يجب أن تكون تركيبات قاعدة البيانات الداعمة للجلسة / الوحدة ميزة أساسية. أي اقتراحات حول كيفية حل هذا؟

ال 15 كومينتر

تستند علامة django_db إلى التركيبات ، ولست متأكدًا من كيفية التواصل بين التركيبات وطرق setup_ *.

هل يمكنك استخدام وحدة نمطية محددة النطاق بدلاً من ذلك لتحقيق نفس الشيء؟ أي شيء من هذا القبيل

pytestmark = pytest.mark.usefixture('test_table')

@pytest.fixture(scope='module')
def test_table(db):
    do_sql('create table ...')

def test_fetch_val():
    assert fetch_val('...') == 1

حاولت فقط. لم يعمل. أحصل على Database access not allowed, use the "django_db" mark to enable الآن.
أيضًا ، test_table() لا يعمل (حاولت رفع الاستثناء هناك)

معذرة ، يجب أن تكون تركيبات مفيدة وليست مفيدة:

http://pytest.org/latest/fixture.html#usefixture

أحصل الآن على ScopeMismatchError: You tried to access the 'function' scoped funcarg 'db' with a 'module' scoped request object, involved factories .

تؤدي إزالة المعلمة db من المعلمة إلى فشل التركيب ، وإزالة النطاق = "الوحدة" تجعل التفكير يعمل ، ولكن يتم تشغيل test_table() لكل اختبار ، وهو ما لا أريده.

حاولت أيضا

pytestmark = pytest.mark.django_db

@pytest.fixture(scope='module')
def test_table():
    do_sql('''
        create table test (
            id int primary key,
            tag int not null
        );

        insert into test values (1, 10), (2, 20);
    ''')

def test_fetch_val(test_table):
    assert fetch_val('select min(id) from test') == 1

def test_fetch_val2(test_table):
    assert fetch_val('select min(id) from test') == 1

الذي يعمل تقريبًا ، لكن الاختبار الثاني يفشل بطريقة ما مع DatabaseError: relation "test" does not exist . لغز كامل بالنسبة لي.

يعمل Django وعلامة django_db بالطريقة التي تعمل بها كل حالة اختبار في معاملتها الخاصة ، وبالتالي فإن استخدام django_db مع وحدة تثبيت مستوى الوحدة النمطية التي تُدخل البيانات في قاعدة البيانات لا معنى له حقًا.

ما هي حالة الاستخدام الخاصة بك هنا؟ كيف يمكنك إنشاء جدول قاعدة بيانات "يدويًا" في اختباراتك ، وليس باستخدام Django ، ولكنك لا تزال تريد استخدام مؤشر قاعدة بيانات الاختبار / اختبار Django؟

ألا يمكنك تحقيق ما تسعى إليه بمجرد إنشاء مؤشر قاعدة بيانات عادي؟

(يتجنب المثال الأخير خطأ ScopeMismatchError ، ولكنه يفشل في الاختبار بدلاً من ذلك لأن المعاملة تم التراجع عنها بعد الاختبار الأول ، وبالتالي تراجع جدول الاختبار.)

أحاول اختبار بعض الأدوات المساعدة منخفضة المستوى ، والتي تستخدم مؤشر django داخليًا - https://github.com/Suor/handy/blob/master/handy/db.py#L40

وأجد أنه سيكون من الأسهل بكثير تحديد نموذج models.py ثم التثبيت في بعض تنسيق django لاختبار ذلك. سيكون هذا عبارة عن 3 ملفات في المجموع لاختبار الوظائف الأساسية جدًا.

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

أوه ، لقد جعلتها تعمل! ساعد التفاف تهيئة SQL إلى begin; ... commit; .

شكرا جزيلا لجميع النصائح التي قدمتها.

هذا اختراق يبدو هشًا بعض الشيء بالنسبة لي. من المحتمل أن أقوم بإعداد تطبيق إضافي يستخدم فقط للاختبارات باستخدام نموذج بسيط يمكنك استخدامه بعد ذلك لتشغيل هذه الوظائف مقابله. يمكنك بعد ذلك بسهولة استخدام ORM في Django لتعبئة البيانات في اختباراتك. إنها كتابة أكثر قليلاً واثنين من الملفات الإضافية ، ولكن بعد ذلك يجب أن تكون آمنة للأعطال المستقبلية.

إذا وجد أي شخص آخر هذه المشكلة: إجراء إعداد قاعدة البيانات في setup_function / setup_class / setup_module ليس مدعومًا أو ممكنًا بأي طريقة جيدة لأن إعداد قاعدة بيانات pytest-django يعتمد على التركيبات.

الحل هو استخدام تركيبات تطلب بشكل صحيح تركيبات db:
http://pytest-django.readthedocs.org/en/latest/helpers.html#db

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

==================================== ERRORS ====================================
___________ ERROR at setup of TestHistoryAlerts.test_one_point_data ____________
ScopeMismatch: You tried to access the 'function' scoped fixture 'db' with a 'session' scoped request object, involved factories
tests/conftest.py:140:  def ts(db)
../../../../.virtualenvs/app/lib/python2.7/site-packages/pytest_django/fixtures.py:158:  def db(request, _django_db_setup, _django_cursor_wrapper)

هل هناك طريقة أخرى للتعامل معها؟

نعم ، هذا هو قيد على db لاعبا اساسيا كما هو مطبق حاليا. في PR # 258 ، كان هناك بعض العمل من أجل إتاحة إمكانية إنشاء حالة قاعدة بيانات مرتبطة بنطاق الفئة / الوحدة / الجلسة.

حتى أن هذه المشكلة الصعبة قديمة جدًا ، فقد وجدت أنه من المفيد العثور على حل لمشكلة كنت أواجهها مع pytest و pytest-django . منذ pytest 3.5.0 هناك مشكلة عند استخدام django_db mark و module مستوى التجهيزات.

أدناه كان يعمل قبل 3.5.0 (على الأقل لم يكن يسبب أي مشاكل).

@pytest.fixture(scope='module')
def user():
    return User.objects.create(...)

@pytest.mark.django_db
def test_some_case(user):
    pass

بعد 3.5.0 يتم رفعها

Failed: Database access not allowed, use the "django_db" mark, or the "db" or "transactional_db" fixtures to enable it.

كان الحل هو إزالة scope='module' .

+1 بالنسبة لي ، مجرد التبديل من بعض اختبارات وحدة Djano الأولية ، يعد هذا عيبًا كبيرًا ، عند تهيئة قاعدة البيانات لحالات اختبار API الخاصة بي. يجب أن تكون تركيبات قاعدة البيانات الداعمة للجلسة / الوحدة ميزة أساسية. أي اقتراحات حول كيفية حل هذا؟

+1

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

القضايا ذات الصلة

rlskoeser picture rlskoeser  ·  7تعليقات

mpasternak picture mpasternak  ·  5تعليقات

clintonb picture clintonb  ·  4تعليقات

ryankask picture ryankask  ·  5تعليقات

asfaltboy picture asfaltboy  ·  5تعليقات