結論(『テスト駆動Python 第2版』より)
複数のテストファイルでフィクスチャを共有したい場合はconftest.pyファイルを使う必要があります。(Kindle版 p.95)
第3章でフィクスチャが詳しく解説されています
目次
複数のテストファイルでフィクスチャを共有したいケース
自明なテストを例に1、フィクスチャの共有に焦点を当てていきます。
- Python 3.11.8
- pytest 8.1.1
2つのテストファイルを配置
. └── tests/ ├── __init__.py # touchしただけ ├── test_1.py └── test_2.py
test_1.py
def test_1_equals_1(): assert 1 == 1
test_2.py
def test_2_equals_2(): assert 2 == 2
1つのファイルにフィクスチャを追加。別のファイルではエラー
test_1.py
にフィクスチャを追加します
import pytest @pytest.fixture def common(): print("Run common fixture") def test_1_equals_1(common): assert 1 == 1
test_2.py
でもこのフィクスチャを使おうとします
-def test_2_equals_2(): +def test_2_equals_2(common): assert 2 == 2
pytest -sv
を実行すると
tests/test_1.py::test_1_equals_1 Run common fixture PASSED tests/test_2.py::test_2_equals_2 ERROR ===================================== ERRORS ====================================== ________________________ ERROR at setup of test_2_equals_2 ________________________ file /.../tests/test_2.py, line 1 def test_2_equals_2(common): E fixture 'common' not found
test_2.py
ではcommon
フィクスチャが見つからずにエラーです
conftest.pyにフィクスチャを定義して解決
.
└── tests/
├── __init__.py
+ ├── conftest.py
├── test_1.py
└── test_2.py
conftest.py
import pytest @pytest.fixture def common(): print("Run common fixture")
test_1.py
def test_1_equals_1(common): assert 1 == 1
test_2.py
def test_2_equals_2(common): assert 2 == 2
pytest -sv
が通ります!
tests/test_1.py::test_1_equals_1 Run common fixture PASSED tests/test_2.py::test_2_equals_2 Run common fixture PASSED
なお『テスト駆動Python』には、conftest.pyもimportすべきでないとあります(pytestにより自動で読み込まれるため)
importでテストは実行できるけれど
私の立場は「conftest.pyを置いて解決すべき」です。
『テスト駆動Python』や(後述する)pytestのドキュメントではconftest.pyが案内されているので、importを使うのは公式から外れたハックであり、可能な限り避けるべきと考えます。
動けばいいという妥協ではなく、ハックなく動作するコードを目指したいですね。
test_2.py
を以下のように変えるとエラーはなくなりますが、決しておすすめはしません。
conftest.pyを使いましょう
from tests.test_1 import common def test_2_equals_2(common): assert 2 == 2
pytestのドキュメントより
「How to use fixtures」の以下
https://docs.pytest.org/en/8.0.x/how-to/fixtures.html#scope-sharing-fixtures-across-classes-modules-packages-or-session
ここでフィクスチャをconftest.pyに切り出すという話が出てきます。
ですが、この箇所はフィクスチャのスコープを扱っていて、conftest.pyについてはあまり言及がありません
「Fixture reference」の中の「conftest.py: sharing fixtures across multiple files」がズバリな項目でした。
https://docs.pytest.org/en/8.0.x/reference/fixtures.html#conftest-py-sharing-fixtures-across-multiple-files
The conftest.py file serves as a means of providing fixtures for an entire directory.
意訳「conftest.pyファイルはディレクトリ全体にフィクスチャを提供する手段に使える」
Fixtures defined in a conftest.py can be used by any test in that package without needing to import them (pytest will automatically discover them).
意訳「conftest.pyに定義されたフィクスチャは、そのパッケージのどのテストにおいても、フィクスチャのインポートの必要なく使える(pytestが自動でフィクスチャを見つける)」
詳細な図示もされています。
この箇所での例から、conftest.pyはディレクトリごとに置けることを知りました。
. └── tests/ ├── __init__.py ├── conftest.py ├── test_top.py └── subpackage/ ├── __init__.py ├── conftest.py └── test_subpackage.py
終わりに
pytestのフィクスチャを共有したいときはconftest.pyを使うことについて見てきました。
■「テストファイルからフィクスチャをimportしてはいけません」
『テスト駆動Python』によると、conftest.pyはローカルプラグインなるもののようです。
読み進めていけば理解が深まりそうです
- 「pytestのフィクスチャは、引数にある別のフィクスチャを実行できる」を確認したときと同じ例です ↩