できない.dev

pytest で「fixture 'xxx' not found」が出てフィクスチャを使えない

テストが要求したフィクスチャが、そのテストから見える範囲に定義されていない。
conftest.py の置き場所、別ファイルでの定義、プラグインの入れ忘れ、綴り違いのどれかで、pytest --fixtures の一覧で切り分けられる。

公開:

要約

テスト関数の引数に書いた名前のフィクスチャが見つからないと、テストは実行前のセットアップで ERROR になる。

file /app/tests/api/test_api.py, line 1
  def test_get(client):
E       fixture 'client' not found
>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, ...
>       use 'pytest --fixtures [testpath]' for help on them.

公式ドキュメントのとおり、フィクスチャが使えるかどうかは「テストの側から見て、定義された範囲に入っているか」で決まる。conftest.py に書いたフィクスチャは、その conftest.py があるディレクトリとその配下のテストにだけ見える。available fixtures の一覧に目的の名前が無ければ、定義はテストから見えていない。

よくある原因

  1. conftest.py の場所がずれている: tests/db/conftest.py に書いたフィクスチャは、tests/api/test_api.py からは見えない。
    兄弟のディレクトリは範囲の外になる。
  2. テストファイルの中で定義している: test_one.py に書いたフィクスチャは test_one.py のテストだけが使える。
    同じディレクトリの test_two.py から要求すると not found になる。
    クラスの中で定義したフィクスチャも、そのクラスのテストに限られる。
  3. プラグインを入れていない: mocker は pytest-mock が提供するフィクスチャで、pytest 本体には無い。
    CI 用の依存に入れ忘れると、手元では通るのに CI だけ落ちる。
  4. 名前の綴りが違う: 引数 clinet はフィクスチャ client とは別物として扱われる。
    ファイル名を conftest.py 以外(confest.py など)にすると、中身は読み込まれない。

解決策

1. conftest.py を共通の上位ディレクトリへ移す

フィクスチャを使うテストが tests/api/ と tests/db/ にまたがるなら、両方を含む tests/ に置く。

tests/
├── conftest.py      # client はここに置く
├── api/
│   └── test_api.py
└── db/
    └── test_db.py

conftest.py のフィクスチャは、テストファイル側で import しなくても使える。
階層ごとに conftest.py を置いた場合は、各階層のフィクスチャがその配下のテストに加わる。

2. 共有するフィクスチャは conftest.py に書く

# tests/conftest.py
import pytest
 
 
@pytest.fixture
def user():
    return {"name": "alice"}

1 つのテストファイルでしか使わないフィクスチャは、そのファイルに置いたままでよい。

3. プラグインを依存に入れる

pip install pytest-mock

プラグインのフィクスチャは、インストールするだけでテスト全体から使えるようになる。requirements-dev.txt などの開発用依存にも書いておく。

4. 見えているフィクスチャを一覧で確かめる

pytest --fixtures tests/api/test_api.py

fixtures defined from conftest の見出しの下に、名前と定義場所(client -- tests/conftest.py:3 のような形)が並ぶ。
ここに出てこなければ、そのテストからは見えていない。
名前が出ているのに not found になるなら、テスト側の引数の綴りを確かめる。

この記事は役立ちましたか?