サーチ…


py.testの設定

py.testは、Pythonで利用可能ないくつかのサードパーティのテストライブラリの 1つです。それはpipを使用してインストールすることができます

pip install pytest

テストするコード

projectroot/module/code.py追加機能をテストしているとします。

# projectroot/module/code.py
def add(a, b):
    return a + b

テストコード

projectroot/tests/test_code.pyテストファイルを作成します。このファイル 、テストファイルとして認識されるには、 test_始まる必要があります。

# projectroot/tests/test_code.py
from module import code


def test_add():
    assert code.add(1, 2) == 3

テストの実行

projectroot我々は単に実行py.test

# ensure we have the modules
$ touch tests/__init__.py
$ touch module/__init__.py
$ py.test
================================================== test session starts ===================================================
platform darwin -- Python 2.7.10, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
rootdir: /projectroot, inifile:
collected 1 items

tests/test_code.py .

================================================ 1 passed in 0.01 seconds ================================================

失敗したテスト

失敗したテストは、何がうまくいかなかったかに関する有用な出力を提供します:

# projectroot/tests/test_code.py
from module import code


def test_add__failing():
    assert code.add(10, 11) == 33

結果:

$ py.test
================================================== test session starts ===================================================
platform darwin -- Python 2.7.10, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
rootdir: /projectroot, inifile:
collected 1 items

tests/test_code.py F

======================================================== FAILURES ========================================================
___________________________________________________ test_add__failing ____________________________________________________

    def test_add__failing():
>       assert code.add(10, 11) == 33
E       assert 21 == 33
E        +  where 21 = <function add at 0x105d4d6e0>(10, 11)
E        +    where <function add at 0x105d4d6e0> = code.add

tests/test_code.py:5: AssertionError
================================================ 1 failed in 0.01 seconds ================================================

テスト器具への紹介

より複雑なテストでは、テストするコードを実行する前に、設定が必要なことがあります。これをテスト機能自体で行うことは可能ですが、大規模なテスト機能が多すぎるため、セットアップがどこで停止し、テストが始まるかを知ることが難しくなります。また、さまざまなテスト機能間で重複したセットアップコードを取得することもできます。

私たちのコードファイル:

# projectroot/module/stuff.py
class Stuff(object):
    def prep(self):
        self.foo = 1
        self.bar = 2

私たちのテストファイル:

# projectroot/tests/test_stuff.py
import pytest
from module import stuff


def test_foo_updates():
    my_stuff = stuff.Stuff()
    my_stuff.prep()
    assert 1 == my_stuff.foo
    my_stuff.foo = 30000
    assert my_stuff.foo == 30000


def test_bar_updates():
    my_stuff = stuff.Stuff()
    my_stuff.prep()
    assert 2 == my_stuff.bar
    my_stuff.bar = 42
    assert 42 == my_stuff.bar

これらは非常に簡単な例ですが、 Stuffオブジェクトにもっと多くの設定が必要な場合は扱いにくくなります。私たちのテストケースの間には重複したコードがあることがわかりますので、まずそれを別の関数にリファクタリングしましょう。

# projectroot/tests/test_stuff.py
import pytest
from module import stuff


def get_prepped_stuff():
    my_stuff = stuff.Stuff()
    my_stuff.prep()
    return my_stuff


def test_foo_updates():
    my_stuff = get_prepped_stuff()
    assert 1 == my_stuff.foo
    my_stuff.foo = 30000
    assert my_stuff.foo == 30000


def test_bar_updates():
    my_stuff = get_prepped_stuff()
    assert 2 == my_stuff.bar
    my_stuff.bar = 42
    assert 42 == my_stuff.bar

これは良く見えますが、私たちはまだmy_stuff = get_prepped_stuff()呼び出しでテスト関数をmy_stuff = get_prepped_stuff()しています。

救助のpy.testの備品!

フィクスチャは、テストセットアップ機能のはるかに強力で柔軟なバージョンです。私たちがここで活用している以上に多くのことを行うことができますが、一度に1ステップずつ進めていきます。

まず、変更get_prepped_stuffと呼ばれる治具にprepped_stuff 。フィクスチャが後でテスト関数でどのように使用されるのかが原因で、動詞ではなく名詞でフィクスチャの名前を付ける必要があります。 @pytest.fixtureは、この特定の関数を通常の関数ではなくフィクスチャーとして処理する必要があることを示します。

@pytest.fixture
def prepped_stuff():
    my_stuff = stuff.Stuff()
    my_stuff.prep()
    return my_stuff

ここで、フィクスチャを使用するようにテスト関数を更新する必要があります。これは、フィクスチャ名と正確に一致するパラメータを定義に追加することによって行われます。 py.testが実行されると、テストを実行する前にフィクスチャを実行し、フィクスチャの戻り値をそのパラメータを介してテスト関数に渡します。 (フィクスチャは値を返す必要はなく、外部リソースを呼び出す、ファイルシステムにアレンジする、データベースに値を入れる、セットアップに必要なテストを行うなどの)他の設定を行うことができます。

def test_foo_updates(prepped_stuff):
    my_stuff = prepped_stuff
    assert 1 == my_stuff.foo
    my_stuff.foo = 30000
    assert my_stuff.foo == 30000


def test_bar_updates(prepped_stuff):
    my_stuff = prepped_stuff
    assert 2 == my_stuff.bar
    my_stuff.bar = 42
    assert 42 == my_stuff.bar

これでなぜ名詞に名前を付けたのか分かります。 my_stuff = prepped_stuff行はかなり役に立たないので、代わりにprepped_stuff直接使用しましょう。

def test_foo_updates(prepped_stuff):
    assert 1 == prepped_stuff.foo
    prepped_stuff.foo = 30000
    assert prepped_stuff.foo == 30000


def test_bar_updates(prepped_stuff):
    assert 2 == prepped_stuff.bar
    prepped_stuff.bar = 42
    assert 42 == prepped_stuff.bar

今は器具を使用しています!フィクスチャの範囲を変更することで(テスト・モジュールごと、またはテスト・ファンクションごとに1回だけ実行する)、他のフィクスチャを使用するフィクスチャを構築し、フィクスチャをパラメータ化することでそのフィクスチャを使用するテストは、フィクスチャに与えられた各パラメータに対して1回、複数回実行されます)、それらを呼び出すモジュールから値を読み取るフィクスチャ...前述のように、フィクスチャは通常のセットアップ機能よりも多くのパワーと柔軟性を備えています。

テスト終了後のクリーンアップ。

コードが大きくなり、Stuffオブジェクトが特別なクリーンアップを必要としているとしましょう。

# projectroot/module/stuff.py
class Stuff(object):
def prep(self):
    self.foo = 1
    self.bar = 2

def finish(self):
    self.foo = 0
    self.bar = 0

すべてのテスト関数の最後にクリーンアップを呼び出すためのコードを追加することができますが、フィクスチャはこれを行うためのより良い方法を提供します。フィクスチャに関数を追加してファイナライザとして登録すると、フィクスチャを使用したテストが完了した後にファイナライザ関数のコードが呼び出されます。フィクスチャのスコープが単一の機能(モジュールやセッションのような)より大きい場合、スコープ内のすべてのテストが完了した後でファイナライザが実行されるため、モジュールの実行が完了した後、またはテスト実行セッションの終了時。

@pytest.fixture
def prepped_stuff(request):  # we need to pass in the request to use finalizers
    my_stuff = stuff.Stuff()
    my_stuff.prep()
    def fin():  # finalizer function
        # do all the cleanup here
        my_stuff.finish()
    request.addfinalizer(fin)  # register fin() as a finalizer
    # you can do more setup here if you really want to
    return my_stuff

関数内でファイナライザ関数を使用することは、特に複雑なフィクスチャを使用している場合には、一目で分かりにくいことがあります。代わりに、 歩留まりフィクスチャを使用して、人間が読める実行フローで同じことを行うことができます。唯一の本当の違いは、代わりに使用することであるreturn我々が使用するyieldのセットアップが完了し、コントロールが後にすべてのクリーンアップコードを追加し、テスト関数に行くべき治具の一部でyield 。また、それをyield_fixtureとしてyield_fixtureし、 yield_fixtureそれをどのように扱うかを知っているようにします。

@pytest.yield_fixture
def prepped_stuff():  # it doesn't need request now!
    # do setup
    my_stuff = stuff.Stuff()
    my_stuff.prep()
    # setup is done, pass control to the test functions
    yield my_stuff
    # do cleanup 
    my_stuff.finish()

そしてそれは、テスト・フィクスチャーの紹介です。

詳細については、 公式のpy.test fixtureのドキュメント公式のyield fixtureのドキュメントを参照してください。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow