Python 如何不回滚在类作用域的pytest django fixture中创建的db事务

Python 如何不回滚在类作用域的pytest django fixture中创建的db事务,python,django,pytest,pytest-django,Python,Django,Pytest,Pytest Django,我正在将pytest与Django(via)一起使用,我想知道是否可能有一个scopeclass的fixture,它在数据库中创建一些模型,然后在每个测试结束时不删除这些模型 比如, @pytest.fixture(scope='class') def expensive(): return MyModel.objects.create() @pytest.mark.django_db() class TestMyModel: def test_a(self, expens

我正在将pytest与Django(via)一起使用,我想知道是否可能有一个scope
class
的fixture,它在数据库中创建一些模型,然后在每个测试结束时不删除这些模型

比如,

@pytest.fixture(scope='class')
def expensive():
    return MyModel.objects.create()


@pytest.mark.django_db()
class TestMyModel:

    def test_a(self, expensive):
          MyModel.objects.get()  # All good

    def test_b(self, expensive):
          MyModel.objects.get()  # raises MyModel.DoesNotExist             
这只是一个简化的例子,在我的实际代码中,fixture
昂贵的
实际上是在做一些需要一些时间的事情(我实际上在使用参数化测试,但我认为这不会有任何区别)。我的愿望是,fixture
中创建的数据一旦超出类的范围,就会回滚,以避免干扰其他测试


似乎我正在尝试使用该装置来完成的工作可能是可行的,但我无法使其按我所希望的方式运行。

在过去几天中,我一直在努力解决同一问题,并设法找到了一个几乎在所有情况下都能正常工作的解决方案。它是基于
pytest-django
源代码进行黑客攻击的。如果将其添加到测试类中,请确保不要添加任何内置的
pytest django
db标记

import psycopg2
from django.apps import apps
from django.test.utils import setup_databases, teardown_databases
# alternatively if you're not on django 1.11 you need
# from pytest_django.compat import setup_databases, teardown_databases

@pytest.fixture(scope='class')
def class_scoped_db(django_db_blocker):
    try:
        django_db_blocker.unblock()
        # if test db exists use it and delete all objects once done
        _ = psycopg2.connect(dbname='test_{your_db_name}')
        yield
        # drop all objects created once we are out of scope
        for app_name in {list of your django apps}:
            for model in apps.get_app_config(app_name).get_models():
                model.objects.all().delete()

    except psycopg2.OperationalError:
        # if test db doesn't exist then create one and tear down once done
        db_cfg = setup_databases(verbosity=pytest.config.option.verbose,
                                 interactive=False)
        yield
        teardown_databases(db_cfg, verbosity=pytest.config.option.verbose)

    finally:
        django_db_blocker.restore()

我发现的一个不起作用的情况是,当运行的第一个需要db访问的测试使用
类\u scoped\u db
时,我认为teardown方法使数据库连接处于一种奇怪的状态,而其余的测试无法使用。在完整的测试运行中,或者在测试单个测试类或模块时,对我来说效果很好

在过去的几天里,我一直在努力解决同一个问题,并设法找到了一个几乎在所有情况下都有效的解决方案。它是基于
pytest-django
源代码进行黑客攻击的。如果将其添加到测试类中,请确保不要添加任何内置的
pytest django
db标记

import psycopg2
from django.apps import apps
from django.test.utils import setup_databases, teardown_databases
# alternatively if you're not on django 1.11 you need
# from pytest_django.compat import setup_databases, teardown_databases

@pytest.fixture(scope='class')
def class_scoped_db(django_db_blocker):
    try:
        django_db_blocker.unblock()
        # if test db exists use it and delete all objects once done
        _ = psycopg2.connect(dbname='test_{your_db_name}')
        yield
        # drop all objects created once we are out of scope
        for app_name in {list of your django apps}:
            for model in apps.get_app_config(app_name).get_models():
                model.objects.all().delete()

    except psycopg2.OperationalError:
        # if test db doesn't exist then create one and tear down once done
        db_cfg = setup_databases(verbosity=pytest.config.option.verbose,
                                 interactive=False)
        yield
        teardown_databases(db_cfg, verbosity=pytest.config.option.verbose)

    finally:
        django_db_blocker.restore()

我发现的一个不起作用的情况是,当运行的第一个需要db访问的测试使用
类\u scoped\u db
时,我认为teardown方法使数据库连接处于一种奇怪的状态,而其余的测试无法使用。在完整测试运行中或在测试单个测试类或模块时,对我来说效果很好

您希望在每次测试后回滚更改,还是在整个测试周期中保留更改,问题的标题是“不回滚”,但测试描述是“我的愿望是,一旦fixture private中创建的数据超出类的范围,就会回滚,这样就不会干扰其他测试。我希望保留在
private
中发生的任何事务,而在测试已回滚。是否要在每次测试后回滚更改,或在整个测试周期中保留更改,问题的标题是“不回滚”,但测试描述是“我的愿望是,一旦fixture private中创建的数据超出类的范围,就会回滚,这样就不会干扰其他测试。我希望保留在
private
中发生的任何事务,而在测试将回滚。