Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 同时使用pytest fixture和peewee事务_Python_Postgresql_Transactions_Pytest_Peewee - Fatal编程技术网

Python 同时使用pytest fixture和peewee事务

Python 同时使用pytest fixture和peewee事务,python,postgresql,transactions,pytest,peewee,Python,Postgresql,Transactions,Pytest,Peewee,我正在使用pytest为一些使用peewee实现的数据库模型编写一组单元测试。我想使用数据库事务(数据库是Postgres数据库,如果相关的话),以便在每次测试后回滚任何数据库更改 我有一种情况,我想在测试中使用两个fixture,但让这两个fixture通过rollback方法清理它们的数据库模型,如下所示: @pytest.fixture def test_model_a(): with db.transaction() as txn: # `db` is my database

我正在使用
pytest
为一些使用
peewee
实现的数据库模型编写一组单元测试。我想使用数据库事务(数据库是Postgres数据库,如果相关的话),以便在每次测试后回滚任何数据库更改

我有一种情况,我想在测试中使用两个fixture,但让这两个fixture通过
rollback
方法清理它们的数据库模型,如下所示:

@pytest.fixture
def test_model_a():
    with db.transaction() as txn:  # `db` is my database object
        yield ModelA.create(...)
        txn.rollback()

@pytest.fixture
def test_model_b():
    with db.transaction() as txn:  # `db` is my database object
        yield ModelB.create(...)
        txn.rollback()

def test_models(test_model_a, test_model_b):
    # ...
这是可行的,但阅读说明这很容易出错:

如果尝试使用
transaction()
上下文管理器将事务嵌套到peewee,则只会使用最外层的事务。但是,如果嵌套块中发生异常,这可能会导致不可预测的行为,因此强烈建议您使用
atomic()

但是,
atomic()
不提供
rollback()
方法。似乎在显式管理事务时,关键是使用最外层的
事务()
,并在该事务中使用
保存点()
上下文管理器。但是在我上面的测试代码中,可以说这两个fixture都在同一个“级别”,我不知道在哪里创建事务,在哪里创建保存点

我唯一的另一个想法是使用对fixture求值的顺序来决定将事务放在何处(),但这看起来确实非常脆弱


有没有办法做到这一点?或者我的测试设计需要重新思考吗?

如果您想回滚在测试中创建的所有事务,您可以使用一个装置来处理事务本身,并使模型装置使用它:

@pytest.fixture
def transaction():
    with db.transaction() as txn:  # `db` is my database object
        yield txn
        txn.rollback()

@pytest.fixture
def test_model_a(txn):
    yield ModelA.create(...)        

@pytest.fixture
def test_model_b(txn):
    yield ModelB.create(...)            

def test_models(test_model_a, test_model_b):
    # ...

这样,所有模型都在同一事务中创建,并在测试结束时回滚

如果要对干净的数据库运行单独的测试,可以使用peewee文档中指定的
数据库.bind_ctx()
模型.bind_ctx()
方法: