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()
方法: