Python|pytestのfixture設計整理法
この記事のポイント
- pytestのfixture設計臭をレビュー視点で読み解ける
- スコープ管理と依存整理技法を学べる
- fixture肥大化を抑止する実務設計文化を体系化できる
- PlantUMLでfixture依存構造の整理イメージを可視化できる
そもそもpytestのfixtureとは
pytestのfixtureは「事前準備(前処理)を再利用可能な注入構造に分離する仕組み」です。
unittestのsetUp()より柔軟に
- スコープ制御(function/module/session)
- 依存注入(fixtureからfixtureを呼ぶ)
- パラメータ化(parametrize対応)
- yield構文で後処理統合
が行えます。
pytest fixture基本例
import pytest
@pytest.fixture
def db():
return MockDatabase()
def test_insert(db):
db.insert("alice")
assert db.count() == 1- テスト関数は引数にfixture名を書く
- pytestが自動注入・実行順序制御
なぜこれをレビューするのか
pytest fixtureは「最初は便利、後に肥大崩壊しやすい」特性を持ちます。
レビューアーは以下を観察する責任を持ちます。
レビューアー視点
- fixture定義が機能単位で整理されているか
- fixture間の依存連鎖が破綻していないか
- スコープ指定が適切に使い分けられているか
- 不要共有(sessionスコープ濫用)が発生していないか
- fixture読解コストが抑えられているか
開発者視点
- fixture依存注入の自由度に油断
- 便利だからfixtureに全部詰め込みがち
- yield前後処理を無意識に積み上げ
- sessionスコープを多用して副作用温床化
fixture崩壊の典型設計臭
崩壊しやすいパターン
- fixtureの中でさらにfixture呼出が連鎖
- データ生成も副作用処理も全てfixture混入
- fixture一個作ると全テストで使いたくなる欲求
- スコープ指定の場当たり適用
- fixtureファイル1個に全部集中肥大
崩壊例:依存連鎖肥大型
依存連鎖例
@pytest.fixture
def db():
return MockDatabase()
@pytest.fixture
def user(db):
db.insert_user("alice")
return "alice"
@pytest.fixture
def order(user, db):
db.insert_order(user, "item123")
return "order123"
def test_order(order):
assert order == "order123"
@Reviewerfixture依存連鎖が進行し読解難度が高まっています。生成責務を個別テスト内に戻す整理も検討してください。
問題点
- fixture層が階層深く可視性低下
- 依存先修正で波及リスク高
崩壊構造モデル:fixture依存肥大構造
fixture整理の設計原則
pytest fixture設計は以下の整理文化が有効です。
① 機能別分割文化
- DB接続 fixture
- 外部API fixture
- ドメイン生成 fixture(必要最小限)
② 最小依存文化
- fixture → fixture 呼出は最小限に抑制
③ スコープ意識文化
| スコープ | 主用途 | 使い過ぎ注意 |
|---|---|---|
| function | 通常使用 | ◯ |
| module | APIレスポンスキャッシュ | △ |
| session | DB準備キャッシュ | ×過剰厳禁 |
④ 明示命名文化
- fixture名は機能語彙優先
- db → db_connection 等
⑤ 副作用封じ文化
- fixture内データ生成責務は原則テスト本体に戻す優先
改善例:依存分離整理
改善整理版
@pytest.fixture
def db_connection():
return MockDatabase()
def create_user(db, username):
db.insert_user(username)
return username
def create_order(db, username, item):
db.insert_order(username, item)
return item
def test_order(db_connection):
user = create_user(db_connection, "alice")
order = create_order(db_connection, user, "item123")
assert order == "item123"「fixtureは環境を用意、データはテストで用意文化」
レビューアーはfixtureとデータ生成の分離文化を推進すると保守性が激変します。
改善構造モデル:責務分離整理
良くない実装例: ケース1(スコープ肥大)
session濫用例
@pytest.fixture(scope="session")
def db():
db = MockDatabase()
yield db
db.close()
@Reviewersessionスコープで全テスト共有されています。副作用制御困難化します。functionスコープ優先に戻してください。
問題点
- テスト独立性崩壊
- 並列実行破綻
良くない実装例: ケース2(fixture多層呼出)
fixture呼出例
@pytest.fixture
def user(db):
db.insert_user("alice")
return "alice"
@pytest.fixture
def order(user, db):
db.insert_order(user, "item123")
return "order123"
@Reviewerfixtureからfixture呼出が連鎖しています。依存整理を優先してください。
問題点
- fixture依存経路肥大化
- 読解負荷上昇
改善例:依存注入分離版
改善版
@pytest.fixture
def db():
return MockDatabase()
def test_order(db):
user = "alice"
db.insert_user(user)
db.insert_order(user, "item123")
assert db.count_order(user) == 1- fixtureは純粋環境提供
- データ生成はテスト内で直列化
観点チェックリスト
まとめ
pytest fixture設計は「再利用文化と肥大文化の表裏一体」です。
レビューアーは「fixture分離文化・依存最小文化・データ生成分離文化」を育成指導することで、長期保守に耐えるpytest設計を維持できます。

