pytest django:无法访问固定装置拆卸中的数据库

kur*_*tgn 5 django pytest pytest-django

我需要在使用夹具后显式删除它。我知道 pytest-django 默认情况下会在拆卸时删除所有对象,但在这种特殊情况下,我需要手动执行此操作。然而,虽然我的测试被标记为pytest.mark.django_db,但我能够创建一个固定装置,但无法在一行后删除它yield

import pytest

from tgapps.models import TelegramApp


@pytest.fixture(scope='module')
def some_fixture():

    app = TelegramApp.objects.create(
        session_data=b'\xa2\x8f#',
        app_owner_phone=79856235474,
        app_id=182475,
        app_hash='aad9ab4384fea1af0342b77b606d13b0'
    )
    yield app

    print('deleting object...')
    app.delete()


class TestTelegramServiceObject(object):

    @pytest.mark.django_db
    def test1(self, some_fixture):
        print('Fixture created:')
        print(some_fixture)
Run Code Online (Sandbox Code Playgroud)

这是我的测试输出:

============================= test session starts ==============================
platform darwin -- Python 3.6.4, pytest-3.4.0, py-1.5.2, pluggy-0.6.0
Django settings: inviter.settings.staging (from ini file)
rootdir: /Users/1111/_projects/fasttrack/inviter, inifile: pytest.ini
plugins: mock-1.7.1, dotenv-0.1.0, django-3.1.2
collected 1 item
test_example.py E.Fixture created:
<79856235474 - 182475>
deleting object...

tests/api/test_example.py:25 (TestTelegramServiceObject.test1)
@pytest.fixture(scope='module')
    def some_fixture():

        app = TelegramApp.objects.create(
            session_data=b'\xa2\x8f#',
            app_owner_phone=79856235474,
            app_id=182475,
            app_hash='aad9ab4384fea1af0342b77b606d13b0'
        )
        yield app

        print('deleting object...')
>       app.delete()

test_example.py:21: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/Users/1111/.virtualenvs/inviter-WB5rPISo/lib/python3.6/site-packages/django/db/models/base.py:890: in delete
    collector.collect([self], keep_parents=keep_parents)
/Users/1111/.virtualenvs/inviter-WB5rPISo/lib/python3.6/site-packages/django/db/models/deletion.py:221: in collect
    elif sub_objs:
/Users/1111/.virtualenvs/inviter-WB5rPISo/lib/python3.6/site-packages/django/db/models/query.py:276: in __bool__
    self._fetch_all()
/Users/1111/.virtualenvs/inviter-WB5rPISo/lib/python3.6/site-packages/django/db/models/query.py:1179: in _fetch_all
    self._result_cache = list(self._iterable_class(self))
/Users/1111/.virtualenvs/inviter-WB5rPISo/lib/python3.6/site-packages/django/db/models/query.py:53: in __iter__
    results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
/Users/1111/.virtualenvs/inviter-WB5rPISo/lib/python3.6/site-packages/django/db/models/sql/compiler.py:1062: in execute_sql
    cursor = self.connection.cursor()
/Users/1111/.virtualenvs/inviter-WB5rPISo/lib/python3.6/site-packages/django/db/backends/base/base.py:255: in cursor
    return self._cursor()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

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

    def _cursor(self, name=None):
>       self.ensure_connection()
E       Failed: Database access not allowed, use the "django_db" mark, or the "db" or "transactional_db" fixtures to enable it.
Run Code Online (Sandbox Code Playgroud)

为什么是这样?以及如何在夹具拆卸时启用数据库评估?

Tom*_*Tom 6

Andreas Profous 提到的固定装置db是功能范围的,因此在这里不起作用。

你需要做的是:

@pytest.fixture(scope='module')
def some_fixture(django_db_setup, django_db_blocker):
    with django_db_blocker.unblock():
        app = TelegramApp.objects.create(
            session_data=b'\xa2\x8f#',
            app_owner_phone=79856235474,
            app_id=182475,
            app_hash='aad9ab4384fea1af0342b77b606d13b0'
        )
    yield app
    with django_db_blocker.unblock():
        print('deleting object...')
        app.delete()
Run Code Online (Sandbox Code Playgroud)

django_db_setup确保测试数据库已设置(并准备好)以添加其他记录。django_db_blockerdb夹具用来允许函数范围内的修改的。它具有函数作用域的原因是,它的行为方式TestCase与默认单元测试框架中的方法的行为方式相同,其中记录在每次测试后回滚。这是一件好事,它确保在一个测试中修改记录不会改变其他测试的结果。

因此,在创建非函数作用域的固定装置时要非常小心,因为默认情况下您的修改不会包装在事务中并回滚。使用django_db_blocker可以让您挂钩该django_db_blocker.unblock()方法,从而消除修改数据库的障碍。这在您的非功能范围固定装置中是必需的。


And*_*ous 0

您需要db在 some_fixture 中引入夹具:

def some_fixture(db): ...