フィクスチャのリファレンス

組み込みフィクスチャ

フィクスチャ@pytest.fixture デコレータを使用して定義されます。 Pytest にはいくつかの便利な組み込みフィクスチャがあります:

capfd

ファイルディスクリプタ 1 と 2 に出力されるテキストをキャプチャします。

capfdbinary

ファイルディスクリプタ 1 と 2 に出力されるバイトをキャプチャします。

caplog

ログの制御とログエントリへのアクセス。

capsys

sys.stdout と sys.stderr に出力されるテキストをキャプチャします。

capsysbinary

sys.stdout と sys.stderr に出力されるバイトをキャプチャします。

cache

pytest の実行間で値を保存および取得します。

doctest_namespace

doctest の名前空間に挿入される dict を提供します。

monkeypatch

クラス、関数、辞書、os.environ などのオブジェクトを一時的に変更します。

pytestconfig

設定値、pluginmanager、およびプラグインフックへのアクセス。

record_property

テストに追加のプロパティを追加します。

record_testsuite_property

テストスイートに追加のプロパティを追加します。

recwarn

テスト関数によって発行された警告を記録します。

request

実行中のテスト関数に関する情報を提供します。

testdir

pytest プラグインの実行とテストを支援するための一時的なテストディレクトリを提供します。

tmp_path

各テスト関数に固有の一時ディレクトリへの pathlib.Path オブジェクトを提供します。

tmp_path_factory

セッションスコープの一時ディレクトリを作成し、pathlib.Path オブジェクトを返します。

tmpdir

各テスト関数に固有の一時ディレクトリへの py.path.local オブジェクトを提供します。 tmp_path に置き換えられました。

tmpdir_factory

セッションスコープの一時ディレクトリを作成し、py.path.local オブジェクトを返します。 tmp_path_factory に置き換えられました。

フィクスチャの利用可能性

フィクスチャの利用可能性はテストの視点から決定されます。 フィクスチャは、そのフィクスチャが定義されているスコープ内にある場合にのみ、テストでリクエストできます。 フィクスチャがクラス内に定義されている場合、そのクラス内のテストでのみリクエストできます。 しかし、フィクスチャがモジュールのグローバルスコープ内に定義されている場合、そのモジュール内のすべてのテスト (クラス内に定義されている場合でも) でリクエストできます。

同様に、テストはそのテストが定義されているスコープ内にある場合にのみ、自動使用フィクスチャの影響を受けることができます (自動使用フィクスチャはそのスコープ内で最初に実行される を参照)。

フィクスチャは、テストが関与するすべてのフィクスチャを参照できる限り、どこに定義されていても他のフィクスチャをリクエストできます。

例えば、スコープ外のフィクスチャ (inner) をリクエストするフィクスチャ (outer) を含むテストファイルは次のようになります:

from __future__ import annotations

import pytest


@pytest.fixture
def order():
    return []


@pytest.fixture
def outer(order, inner):
    order.append("outer")


class TestOne:
    @pytest.fixture
    def inner(self, order):
        order.append("one")

    def test_order(self, order, outer):
        assert order == ["one", "outer"]


class TestTwo:
    @pytest.fixture
    def inner(self, order):
        order.append("two")

    def test_order(self, order, outer):
        assert order == ["two", "outer"]

テストの視点から見ると、依存している各フィクスチャを問題なく参照できます:

../_images/test_fixtures_request_different_scope.svg

したがって、テストが実行されるとき、pytest はテストの視点から検索するため、outer は inner を問題なく見つけることができます。

注釈

フィクスチャが定義されているスコープは、そのインスタンス化の順序には影響しません。 順序は こちら で説明されているロジックによって決定されます

conftest.py: 複数のファイル間でフィクスチャを共有する

conftest.py ファイルは、ディレクトリ全体にフィクスチャを提供する手段として機能します。 conftest.py に定義されたフィクスチャは、そのパッケージ内の任意のテストでインポートすることなく使用できます (pytest が自動的にそれらを検出します)。

複数のネストされたディレクトリ/パッケージにテストを含めることができ、各ディレクトリには独自のフィクスチャを持つ独自の conftest.py を持つことができ、親ディレクトリの conftest.py ファイルによって提供されるフィクスチャに追加されます。

例えば、次のようなテストファイル構造がある場合:

tests/
    __init__.py

    conftest.py
        # content of tests/conftest.py
        import pytest

        @pytest.fixture
        def order():
            return []

        @pytest.fixture
        def top(order, innermost):
            order.append("top")

    test_top.py
        # content of tests/test_top.py
        import pytest

        @pytest.fixture
        def innermost(order):
            order.append("innermost top")

        def test_order(order, top):
            assert order == ["innermost top", "top"]

    subpackage/
        __init__.py

        conftest.py
            # content of tests/subpackage/conftest.py
            import pytest

            @pytest.fixture
            def mid(order):
                order.append("mid subpackage")

        test_subpackage.py
            # content of tests/subpackage/test_subpackage.py
            import pytest

            @pytest.fixture
            def innermost(order, mid):
                order.append("innermost subpackage")

            def test_order(order, top):
                assert order == ["mid subpackage", "innermost subpackage", "top"]

スコープの境界は次のように視覚化できます:

../_images/fixture_availability.svg

ディレクトリはそれ自体がスコープの一種となり、そのディレクトリ内の conftest.py ファイルに定義されたフィクスチャがそのスコープ全体で利用可能になります。

テストはフィクスチャを探すために上方向 (円の外側) に検索することが許可されていますが、下方向 (円の内側) に検索を続けることはできません。 したがって、tests/subpackage/test_subpackage.py::test_ordertests/subpackage/test_subpackage.py に定義された innermost フィクスチャを見つけることができますが、tests/test_top.py に定義されたフィクスチャは見つけることができません。

テストが最初に見つけたフィクスチャが使用されるため、特定のスコープに対してフィクスチャを変更または拡張する必要がある場合は、フィクスチャをオーバーライドする ことができます。

また、conftest.py ファイルを使用して ローカルなディレクトリごとのプラグイン を実装することもできます。

サードパーティプラグインからのフィクスチャ

ただし、フィクスチャはこの構造で定義されていなくてもテストで利用可能です。 サードパーティプラグインによって提供されることもあり、多くの pytest プラグインがこの方法で動作します。 これらのプラグインがインストールされている限り、それらが提供するフィクスチャはテストスイートのどこからでもリクエストできます。

これらのフィクスチャはテストスイートの構造外から提供されるため、サードパーティプラグインは conftest.py ファイルやテストスイート内のディレクトリのようなスコープを実際には提供しません。 その結果、pytest は前述のようにスコープを通じてフィクスチャを検索し、最後にプラグインに定義されたフィクスチャに到達します。

例えば、次のファイル構造があるとします:

tests/
    __init__.py

    conftest.py
        # content of tests/conftest.py
        import pytest

        @pytest.fixture
        def order():
            return []

    subpackage/
        __init__.py

        conftest.py
            # content of tests/subpackage/conftest.py
            import pytest

            @pytest.fixture(autouse=True)
            def mid(order, b_fix):
                order.append("mid subpackage")

        test_subpackage.py
            # content of tests/subpackage/test_subpackage.py
            import pytest

            @pytest.fixture
            def inner(order, mid, a_fix):
                order.append("inner subpackage")

            def test_order(order, inner):
                assert order == ["b_fix", "mid subpackage", "a_fix", "inner subpackage"]

plugin_a がインストールされていて a_fix フィクスチャを提供し、plugin_b がインストールされていて b_fix フィクスチャを提供している場合、テストのフィクスチャ検索は次のようになります:

../_images/fixture_availability_plugins.svg

pytest は最初に tests/ 内のスコープで a_fixb_fix を検索し、その後にプラグインで検索します。

フィクスチャのインスタンス化順序

pytest がテストを実行しようとするとき、どのフィクスチャが実行されるかがわかると、それらが実行される順序を決定する必要があります。 これを行うために、pytest は次の3つの要素を考慮します:

  1. スコープ

  2. 依存関係

  3. 自動使用

フィクスチャやテストの名前、それらが定義されている場所、定義されている順序、フィクスチャがリクエストされる順序は、偶然以外の実行順序には影響しません。 pytest はこれらの偶然が実行ごとに一貫していることを確認しようとしますが、それに依存するべきではありません。 順序を制御したい場合は、これらの3つの要素に依存し、依存関係が明確に確立されていることを確認するのが最も安全です。

高スコープのフィクスチャが最初に実行される

フィクションリクエスト内では、高スコープ (例えば session) のフィクスチャが低スコープ (例えば functionclass) のフィクスチャよりも先に実行されます。

例を示します:

from __future__ import annotations

import pytest


@pytest.fixture(scope="session")
def order():
    return []


@pytest.fixture
def func(order):
    order.append("function")


@pytest.fixture(scope="class")
def cls(order):
    order.append("class")


@pytest.fixture(scope="module")
def mod(order):
    order.append("module")


@pytest.fixture(scope="package")
def pack(order):
    order.append("package")


@pytest.fixture(scope="session")
def sess(order):
    order.append("session")


class TestClass:
    def test_order(self, func, cls, mod, pack, sess, order):
        assert order == ["session", "package", "module", "class", "function"]

テストは、より大きなスコープのフィクスチャが最初に実行されるため、成功します。

順序は次のようになります:

../_images/test_fixtures_order_scope.svg

同じ順序のフィクスチャは依存関係に基づいて実行される

フィクスチャが他のフィクスチャをリクエストすると、そのフィクスチャが最初に実行されます。 したがって、フィクスチャ a がフィクスチャ b をリクエストすると、フィクスチャ b が最初に実行されます。 なぜなら、ab に依存しており、b なしでは動作できないからです。 ab の結果を必要としない場合でも、b の後に実行される必要がある場合は b をリクエストできます。

例えば:

from __future__ import annotations

import pytest


@pytest.fixture
def order():
    return []


@pytest.fixture
def a(order):
    order.append("a")


@pytest.fixture
def b(a, order):
    order.append("b")


@pytest.fixture
def c(b, order):
    order.append("c")


@pytest.fixture
def d(c, b, order):
    order.append("d")


@pytest.fixture
def e(d, b, order):
    order.append("e")


@pytest.fixture
def f(e, order):
    order.append("f")


@pytest.fixture
def g(f, c, order):
    order.append("g")


def test_order(g, order):
    assert order == ["a", "b", "c", "d", "e", "f", "g"]

依存関係をマッピングすると、次のようになります:

../_images/test_fixtures_order_dependencies.svg

各フィクスチャが従うべきルール (各フィクスチャがどのフィクスチャの後に来る必要があるか) は包括的であり、次のようにフラット化できます:

../_images/test_fixtures_order_dependencies_flat.svg

pytest が明確で線形な依存関係のチェーンを把握できるようにするために、これらのリクエストを通じて十分な情報が提供される必要があります。 曖昧さがあり、操作の順序が複数の方法で解釈できる場合、pytest はその時点で任意の解釈を選択する可能性があると考えるべきです。

例えば、dc をリクエストしなかった場合、グラフは次のようになります:

../_images/test_fixtures_order_dependencies_unclear.svg

c をリクエストしたのは g だけであり、gf もリクエストしているため、cfe、または d の前後のどこに配置されるべきかが不明確です。 c に設定された唯一のルールは、b の後、g の前に実行される必要があるということです。

pytest はこの場合、c がどこに配置されるべきかを知らないため、bg の間のどこにでも配置される可能性があると考えるべきです。

これは必ずしも悪いことではありませんが、覚えておくべきことです。 実行順序がテストのターゲットとなる動作に影響を与える可能性がある場合、またはテストの結果に影響を与える可能性がある場合は、その順序を明確に定義し、pytest がその順序を線形化/「フラット化」できるようにする必要があります。

自動使用フィクスチャはそのスコープ内で最初に実行される

自動使用フィクスチャは、それを参照できるすべてのテストに適用されると見なされるため、そのスコープ内の他のフィクスチャよりも先に実行されます。 自動使用フィクスチャによってリクエストされたフィクスチャは、実際の自動使用フィクスチャが適用されるテストに対して自動使用フィクスチャ自体になります。

したがって、フィクスチャ a が自動使用であり、フィクスチャ b がそうでない場合でも、フィクスチャ a がフィクスチャ b をリクエストすると、フィクスチャ b は実質的に自動使用フィクスチャとなりますが、a が適用されるテストに対してのみです。

前の例では、dc をリクエストしなかった場合、グラフは不明確になりました。 しかし、c が自動使用であれば、ba も実質的に自動使用となります。 なぜなら、c がそれらに依存しているからです。 その結果、それらはそのスコープ内の非自動使用フィクスチャの上にシフトされます。

したがって、テストファイルが次のようになっている場合:

from __future__ import annotations

import pytest


@pytest.fixture
def order():
    return []


@pytest.fixture
def a(order):
    order.append("a")


@pytest.fixture
def b(a, order):
    order.append("b")


@pytest.fixture(autouse=True)
def c(b, order):
    order.append("c")


@pytest.fixture
def d(b, order):
    order.append("d")


@pytest.fixture
def e(d, order):
    order.append("e")


@pytest.fixture
def f(e, order):
    order.append("f")


@pytest.fixture
def g(f, c, order):
    order.append("g")


def test_order_and_g(g, order):
    assert order == ["a", "b", "c", "d", "e", "f", "g"]

グラフは次のようになります:

../_images/test_fixtures_order_autouse.svg

c がグラフ内で d の上に配置できるようになったため、pytest は再びグラフを次のように線形化できます:

../_images/test_fixtures_order_autouse_flat.svg

この例では、cba を実質的に自動使用フィクスチャにします。

ただし、自動使用には注意が必要です。 自動使用フィクスチャは、それを参照できるすべてのテストに対して自動的に実行されます。 たとえそれらがリクエストされていなくてもです。 例えば、次のファイルを考えてみてください:

from __future__ import annotations

import pytest


@pytest.fixture(scope="class")
def order():
    return []


@pytest.fixture(scope="class", autouse=True)
def c1(order):
    order.append("c1")


@pytest.fixture(scope="class")
def c2(order):
    order.append("c2")


@pytest.fixture(scope="class")
def c3(order, c1):
    order.append("c3")


class TestClassWithC1Request:
    def test_order(self, order, c1, c3):
        assert order == ["c1", "c3"]


class TestClassWithoutC1Request:
    def test_order(self, order, c2):
        assert order == ["c1", "c2"]

TestClassWithoutC1Request 内のテストは何も c1 をリクエストしていないにもかかわらず、それでも実行されます:

../_images/test_fixtures_order_autouse_multiple_scopes.svg

ただし、1つの自動使用フィクスチャが非自動使用フィクスチャをリクエストしたからといって、その非自動使用フィクスチャがそれが適用されるすべてのコンテキストに対して自動使用フィクスチャになるわけではありません。 それは、実際の自動使用フィクスチャ (非自動使用フィクスチャをリクエストしたもの) が適用されるコンテキストに対してのみ実質的に自動使用フィクスチャになります。

例えば、次のテストファイルを見てみましょう:

from __future__ import annotations

import pytest


@pytest.fixture
def order():
    return []


@pytest.fixture
def c1(order):
    order.append("c1")


@pytest.fixture
def c2(order):
    order.append("c2")


class TestClassWithAutouse:
    @pytest.fixture(autouse=True)
    def c3(self, order, c2):
        order.append("c3")

    def test_req(self, order, c1):
        assert order == ["c2", "c3", "c1"]

    def test_no_req(self, order):
        assert order == ["c2", "c3"]


class TestClassWithoutAutouse:
    def test_req(self, order, c1):
        assert order == ["c1"]

    def test_no_req(self, order):
        assert order == []

次のように分解されます:

../_images/test_fixtures_order_autouse_temp_effects.svg

TestClassWithAutouse 内の test_reqtest_no_req に対して、c3c2 を実質的に自動使用フィクスチャにします。 これが、c2c3 がリクエストされていないにもかかわらず両方のテストで実行される理由であり、test_req に対して c1 の前に c2c3 が実行される理由です。

これが c2実際の 自動使用フィクスチャにした場合、TestClassWithoutAutouse 内のテストに対しても c2 が実行されます。 なぜなら、それらが c2 を参照できるからです。 しかし、そうではありません。 なぜなら、TestClassWithoutAutouse のテストの観点からは、c2 は自動使用フィクスチャではないからです。 なぜなら、それらは c3 を見ることができないからです。