Pytest-django: يتخطى pytest 5.4 تفكيك Django (مما يتسبب على سبيل المثال في أخطاء "الاتصال مغلق بالفعل")

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

بيتيست- دجانغو == 3.5.1
تم اختبار إصدارات django: 2.2.11 و 3.0.4

عندما يفشل اختبار واحد ، ستفشل جميع الاختبارات التي تستخدم قاعدة البيانات التي تم تشغيلها بعد هذا الاختبار مع traceback:

test/apiv2/put_inputevent__test.py:34: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/home/u1/.virtualenvs/npserver/lib/python3.7/site-packages/model_mommy/mommy.py:54: in make
    return mommy.make(_save_kwargs=_save_kwargs, **attrs)
/home/u1/.virtualenvs/npserver/lib/python3.7/site-packages/model_mommy/mommy.py:228: in make
    return self._make(commit=True, commit_related=True, _save_kwargs=_save_kwargs, **attrs)
/home/u1/.virtualenvs/npserver/lib/python3.7/site-packages/model_mommy/mommy.py:265: in _make
    instance = self.instance(self.model_attrs, _commit=commit, _save_kwargs=_save_kwargs)
/home/u1/.virtualenvs/npserver/lib/python3.7/site-packages/model_mommy/mommy.py:289: in instance
    instance.save(**_save_kwargs)
/home/u1/.virtualenvs/npserver/lib/python3.7/site-packages/django/db/models/base.py:741: in save
    force_update=force_update, update_fields=update_fields)
/home/u1/.virtualenvs/npserver/lib/python3.7/site-packages/django/db/models/base.py:779: in save_base
    force_update, using, update_fields,
/home/u1/.virtualenvs/npserver/lib/python3.7/site-packages/django/db/models/base.py:851: in _save_table
    forced_update)
/home/u1/.virtualenvs/npserver/lib/python3.7/site-packages/django/db/models/base.py:900: in _do_update
    return filtered._update(values) > 0
/home/u1/.virtualenvs/npserver/lib/python3.7/site-packages/django/db/models/query.py:760: in _update
    return query.get_compiler(self.db).execute_sql(CURSOR)
/home/u1/.virtualenvs/npserver/lib/python3.7/site-packages/django/db/models/sql/compiler.py:1469: in execute_sql
    cursor = super().execute_sql(result_type)
/home/u1/.virtualenvs/npserver/lib/python3.7/site-packages/django/db/models/sql/compiler.py:1138: in execute_sql
    cursor = self.connection.cursor()
/home/u1/.virtualenvs/npserver/lib/python3.7/site-packages/django/db/backends/base/base.py:256: in cursor
    return self._cursor()
/home/u1/.virtualenvs/npserver/lib/python3.7/site-packages/django/db/backends/base/base.py:235: in _cursor
    return self._prepare_cursor(self.create_cursor(name))
/home/u1/.virtualenvs/npserver/lib/python3.7/site-packages/django/db/utils.py:89: in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
/home/u1/.virtualenvs/npserver/lib/python3.7/site-packages/django/db/backends/base/base.py:235: in _cursor
    return self._prepare_cursor(self.create_cursor(name))
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <django.db.backends.postgresql.base.DatabaseWrapper object at 0x7fe8150ed208>, name = None

    def create_cursor(self, name=None):
        if name:
            # In autocommit mode, the cursor will be used outside of a
            # transaction, hence use a holdable cursor.
            cursor = self.connection.cursor(name, scrollable=False, withhold=self.connection.autocommit)
        else:
>           cursor = self.connection.cursor()
E           django.db.utils.InterfaceError: connection already closed

/home/u1/.virtualenvs/npserver/lib/python3.7/site-packages/django/db/backends/postgresql/base.py:223: InterfaceError

الرجوع إلى إصدار pytest == 5.3.5 يعمل على إصلاح المشكلة.

لست متأكدًا حتى الآن مما إذا كانت هذه مشكلة pytest أم pytest-django.

bug

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

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

ال 22 كومينتر

هل يمكنك تأكيد حدوث ذلك أيضًا في pytest 5.4.1؟

إذا كانت الإجابة بنعم ، فسيكون الحد الأدنى من التكاثر أمرًا رائعًا.

نعم ، 5.4.1 أيضًا. سنحاول إنشاء حالة صغيرة.

تم إنشاء مشروع django الصغير: https://github.com/Fak3/testproject-824-git

شكرا للتكاثر!

بدا لي وكأنه مشكلة في دعم pytest غير اللائق ، لذلك نظرت إلى التغييرات التي تم إجراؤها على ذلك في pytest في 5.4.x. يؤدي الرجوع إلى https://github.com/pytest-dev/pytest/pull/5996 "unittest: لا تستخدم TestCase.debug () مع --pdb " (والتزامات أخرى في تلك العلاقات العامة) إلى إصلاح المشكلة.

سم مكعبblueyednicoddemus الذين عملوا على أن العلاقات العامة، وربما يكون لديك فكرة أفضل مني.

@ Fak3
يرجى محاولة https://github.com/pytest-dev/pytest-django/pull/825.
تكمن المشكلة في أنه لم يتم استدعاء تفكيك Django (المخصص إلى حد ما) (لأن هذا يطرح استثناءً للخروج من unittest __call__ ، بحيث يمكن استخدام --pdb قبل أي تفكيك - على الرغم من أنه يمكنك أضف أيضًا pdb.set_tracce() وانتهى الأمر).

(إنها الجولة التالية من الإصدار الذي طال أمده منذ عام 2016 ، وما زلت أعتقد أنه كان يجب إعادتها أولاً على الأقل بدلاً من ذلك (راجع https://github.com/pytest-dev/pytest/pull/6014) ، حتى ذلك الحين يتم إجراؤه بشكل صحيح ، على سبيل المثال عبر شيء مثل https://github.com/blueyed/pytest/pull/107))

يمكن لـ pytest-django اعتراض دجانجو _post_teardown (https://github.com/django/django/blob/1a09708dcb2f60ad5ca0a75b8de9619356f74ff6/django/test/testcases.py#L274) ، ولكن افعل ذلك بعد المكالمة لا تزال بحاجة إلى التصحيح الأول pytest لعدم استخدام النهج الحالي.

من فضلك جرب # 825.

نعم ، هذا العلاقات العامة يصلح هذه المشكلة

هل pytest-dev / pytest # 6947 مرتبط؟

نعم ، بسبب ذلك.

ثابت في pytest-django 3.9.0 الآن.

أعتقد أن المشكلة لا تزال قائمة في pytest-django 3.9.0 # 835

أعتقد أن المشكلة لا تزال قائمة في pytest-django 3.9.0 # 835

نفس المشكلة هنا!

@ PyB1l أو @ hugos94 ، هل هناك فرصة لاختبار هذا باستخدام أحدث master pytest؟ إذا استمرت المشكلة ، سأكون ممتنًا لمشروع صغير لإعادة إنتاج المشكلة (المشروع المقدم في https://github.com/pytest-dev/pytest-django/issues/824#issuecomment-598857918 يعود الآن 404).

بالنسبة لاختباراتي ، تمكنت من عزل المشكلة في Django == 3.0.2. بالنسبة إلى Django === 3.0.5 وجميع الإصدارات الأخيرة من pytest ، pytest-django ، ليس لدي أي مشاكل. @ hugos94 هل يمكنك التحقق من

بالنسبة لاختباراتي ، تمكنت من عزل المشكلة في Django == 3.0.2. بالنسبة إلى Django === 3.0.5 وجميع الإصدارات الأخيرة من pytest ، pytest-django ، ليس لدي أي مشاكل. @ hugos94 هل يمكنك التحقق من

أنا أستخدم الإصدارات التالية:

  • جانغو == 2.2.7
  • بيتيست == 5.4.1
  • بيتيست- دجانغو == 3.9.0

يبدو أن المشكلة تحدث فقط بعد تقديم طلبات في وجهات نظر التطبيق. في الاختبارات التي أستخدمها Graphql ، لا يحدث الخطأ.

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

أهلا،

يبدو أن المشكلة عادت إلى الظهور:

  • pip install -U pytest-django!=4.3.0 ثم pytest = 626 passed, 6 skipped, 70 warnings
  • pip install -U pytest-django==4.3.0 ثم pytest = 8 failed, 618 passed, 6 skipped, 70 warnings

هناك مشكلة في الاختبارين التاليين فقط ، وهو أمر غريب بالنظر إلى العدد الكبير من الاختبارات التي لا تزال تعمل بشكل جيد:

@pytest.mark.parametrize('email', (
        '[email protected]',
        '[email protected]',
        '[email protected]',
        '[email protected]',
        '[email protected]',
        't!#$%&es!#$%&[email protected]',
        # Those are NOT valid, but we accept them to avoid an overly
        # complicated regex. In any case, the true validation SHOULD be to send
        # a confirmation email.
        '[email protected]',
    ))
    @pytest.mark.django_db
    def test_email_valid(self, db_setup_company: Company, email: str) -> None:
        company = db_setup_company

        user = User.objects.create(email=email, company=company)

        assert list(user.building_ids) == []

    @pytest.mark.parametrize('email', (
        'aaaa@[email protected]',
        '@@@test@@@@tld-minus.com',
    ))
    @pytest.mark.django_db
    def test_email_invalid(self, db_setup_company: Company, email: str) -> None:
        company = db_setup_company

        with pytest.raises(IntegrityError) as exc:
            User.objects.create(email=email, company=company)

        assert 'violates check constraint "email_valid_chk"' in str(exc)

freeze.txt

لقد لاحظت هذه المشكلة أيضًا. هل تفضل إعادة فتح هذا الخطأ أو إنشاء عدد جديد؟ FWIW ، ها هي قائمة التبعيات الأخرى الخاصة بي.

django==3.0.14
pytest-cov==2.12.0
pytest-env==0.6.2
pytest-forked==1.3.0
pytest-freezegun==0.4.2
pytest-instafail==0.4.2
pytest-mock==3.6.1
pytest-socket==0.4.0
pytest-subtests==0.4.0
pytest-vcr==1.0.2
pytest-xdist==2.2.1
pytest==6.2.4

يختلف إصدار Django عن nathanprat (3.0 مقابل 3.2) لذا لا يبدو ذا صلة. أرى ثلاث نقاط مشتركة مع ما ورد أعلاه freeze.txt :

pytest==6.2.4
pytest-django==4.3.0
pytest-mock==3.6.1

تحديث:

بعد إجراء مزيد من التحقيق ، قمت بإنشاء مشروع بسيط بدون مشكلة ، يمكنك رؤية الفشل في تنفيذ الإجراءات.

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

browniebroke إذا كنت ترغب في ذلك ، هل يمكن أن تشرح سبب تسبب هذا

لا أعرف السبب (حتى الآن) لسوء الحظ ، لقد تمكنت للتو من عزل هذا باعتباره السبب الجذري ، لكنني لم أستمر في الترقية بسبب ضيق الوقت.

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

شكرا على التحقيق.

كان سبب الخطأ بالفعل هو تثبيت db على مستوى الفئة.

ليس لدي وقت للتحقيق بشكل أعمق في الوقت الحالي ، ولكن الكود موجود أدناه إذا كان أي شخص مهتمًا:

@pytest.fixture(name='class_db', scope='class')
def fixture_class_db(request: 'Any',
                     django_db_setup: 'Any',  # pylint: disable=unused-argument
                     django_db_blocker: 'Any') -> None:
    """
    To avoid the error with 'fixture_db_setup(db)':

    "ScopeMismatch: You tried to access the 'function' scoped fixture 'db'
    with a 'module' scoped request object, involved factories"

    We reimplement a 'db'-like fixture class-scoped.
    """
    # Copy-pasted from pytest_django.fixtures
    if "django_db_reset_sequences" in request.fixturenames:
        request.getfixturevalue("django_db_reset_sequences")
    if ("transactional_db" in request.fixturenames
            or "live_server" in request.fixturenames):
        request.getfixturevalue("transactional_db")
    else:
        _django_db_fixture_helper(
            request,
            django_db_blocker,
            transactional=False)

browniebroke إذا قمت بتغيير الكود الخاص بك من django_db_blocker.unblock() إلى with django_db_blocker.unblock(): ... فهل هذا مفيد ؟

شكرا على اقتراح bluetech. لقد جربت اقتراحك (على ما أعتقد) ولكن لم يحالفني الحظ بعد ... هل كان هذا هو الحل الذي تفكر فيه؟

نعم. على الرغم من أنه كان صحيحًا أيضًا من قبل ، إلا أن عيني ألقت نظرة سريعة على المكالمات addfinalizer . نظرًا لأنك تستخدم الآن مدير سياق ، يجب أن تكون قادرًا على إزالة request.addfinalizer(django_db_blocker.restore) . يمكنك أيضًا تحويل request.addfinalizer(functools.partial(TestCase._rollback_atomics, atomics)) إلى مكالمة عادية بعد yield .

(أفهم أن هذا لا يحل مشكلتك في الواقع. ما أعتقد أنك تحاول تحقيقه - المشاركة الآمنة لبيانات قاعدة البيانات بعد اختبار واحد - هو حاليًا ميزة مفقودة في pytest-django)

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

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

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

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

aljosa picture aljosa  ·  8تعليقات

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

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