2016-09-20 23 views
2

peeweeを使用して実装されている一部のデータベースモデルでは、pytestを使用して単体テストのセットを作成しています。各テストの後にデータベースの変更をロールバックするために、データベーストランザクションを使用したい(データベースはPostgresのものです)。pytest fixturesとpeeweeトランザクションを一緒に使用する

私はテストで2つの備品を使用したい状況があるが、両方の備品がそうのように、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()コンテキストマネージャを使用してピーウィーで巣取引しようとすると、唯一の最も外側のトランザクションが使用されます。documentation for peeweeが、これは誤りがちであることを示唆しています。ただし、ネストされたブロックで例外が発生すると、予期しない動作が発生する可能性があるため、atomic()を使用することを強くお勧めします。

しかし、atomic()は、rollback()メソッドを提供しません。トランザクションを明示的に管理する場合、鍵は外側のtransaction()を使用し、そのトランザクション内でsavepoint()コンテキストマネージャを使用することです。しかし、上のテストコードでは、両方のフィクスチャは同じ「レベル」にあります。つまり、トランザクションを作成する場所とセーブポイントを作成する場所はわかりません。

私の唯一のアイデアは、治具が評価される順序を使ってトランザクションをどこに置くかを決めることです(which seems to be alphabetical)が、これは確かに非常に脆いようです。

これを達成する方法はありますか?または、私のテストデザインは再考が必要ですか?

答えて

3

あなたがテスト中に作成されたすべてのトランザクションをロールバックする場合は、トランザクション自体の世話をし、モデルの備品がそれを使用するようフィクスチャを持つことができます:

@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): 
    # ... 

この方法ですべてのモデルは内に作成されていますテストの終了時には同じトランザクションがロールバックされます。

関連する問題