web-dev-qa-db-ja.com

テストでpytestクラスを正しくセットアップして分解するにはどうすればよいですか?

エンドツーエンドのテストにSeleniumを使用していますが、setup_classおよびteardown_classメソッドの使用方法がわかりません。

ブラウザをsetup_classメソッドで設定し、クラスメソッドとして定義された一連のテストを実行し、最後にteardown_classメソッドでブラウザを終了する必要があります。

しかし、実際には私のテストはクラスではなくオブジェクトで機能するため、論理的には悪い解決策のようです。すべてのテストメソッド内でself paramを渡すので、オブジェクトの変数にアクセスできます。

class TestClass:

    def setup_class(cls):
        pass

    def test_buttons(self, data):
        # self.$attribute can be used, but not cls.$attribute?  
        pass

    def test_buttons2(self, data):
        # self.$attribute can be used, but not cls.$attribute?
        pass

    def teardown_class(cls):
        pass

また、クラスのブラウザインスタンスを作成することは正しくないようです。すべてのオブジェクトに対して個別に作成する必要があります。

だから、__init____del__の代わりにsetup_classteardown_classメソッドを使用する必要がありますか?

61
avasin

フィクスチャのファイナライゼーション/分解コードの実行addfinalizerの使用は「歴史的」です。

歴史的なメモとして、分解コードを記述する別の方法は、フィクスチャ関数にリクエストオブジェクトを受け入れ、そのrequest.addfinalizerを1回または複数回呼び出すことです。

現在のセットアップと分解のベストプラクティスは、yieldを使用することです

import pytest

@pytest.fixture()
def resource():
    print("setup")
    yield "resource"
    print("teardown")

class TestResource(object):
    def test_that_depends_on_resource(self, resource):
        print("testing {}".format(resource))

実行すると

$ py.test --capture=no pytest_yield.py
=== test session starts ===
platform darwin -- Python 2.7.10, pytest-3.0.2, py-1.4.31, pluggy-0.3.1
collected 1 items

pytest_yield.py setup
testing resource
.teardown


=== 1 passed in 0.01 seconds ===
58
Everett Toews

"クラスメソッドとして定義されたテスト"を書くとき、本当にclassメソッド(そのclassを最初のパラメーターとして)または単なる通常のメソッド(instanceを最初のパラメーターとして受け取るメソッド) )?

あなたの例はテストメソッドにselfを使用しているので、後者を想定しているので、代わりにsetup_methodを使用するだけです。

class Test:

    def setup_method(self, test_method):
        # configure self.attribute

    def teardown_method(self, test_method):
        # tear down self.attribute

    def test_buttons(self):
        # use self.attribute for test

テストメソッドインスタンスはsetup_methodおよびteardown_methodに渡されますが、セットアップ/ティアダウンコードがテストコンテキストを知る必要がない場合は無視できます。詳細については、 こちら をご覧ください。

また、py.testの fixtures はより強力な概念であるため、py.testに精通することをお勧めします。

43
Bruno Oliveira

@Brunoが示唆したように、pytestフィクスチャを使用することは、両方のテストクラスまたは単純なテスト関数からでもアクセスできる別のソリューションです。 python2.7関数のテスト例

import pytest

@pytest.fixture(scope='function')
def some_resource(request):
    stuff_i_setup = ["I setup"]

    def some_teardown():
        stuff_i_setup[0] += " ... but now I'm torn down..."
        print stuff_i_setup[0]
    request.addfinalizer(some_teardown)

    return stuff_i_setup[0]

def test_1_that_needs_resource(some_resource):
    print some_resource + "... and now I'm testing things..."

したがって、test_1...を実行すると、以下が生成されます。

I setup... and now I'm testing things...
I setup ... but now I'm torn down...

フィクスチャ内でstuff_i_setupが参照されていることに注意してください。これにより、オブジェクトが相互作用するテストに対してsetupおよびtorn downになります。これは、仮想データベースや接続などの永続オブジェクトに役立ち、各テストを実行する前にそれらを隔離しておく必要があると想像できます。

23
ecoe

これは役立つかもしれません http://docs.pytest.org/en/latest/xunit_setup.html

テストスイートでは、テストケースをクラスにグループ化します。そのクラスのすべてのテストケースに必要なセットアップと分解には、setup_class(cls)およびteardown_class(cls)クラスメソッドを使用します。

そして、各テストケースに必要なセットアップと分解には、setup_method(method)teardown_method(methods)を使用します

例:

lh = <got log handler from logger module>

class TestClass:
    @classmethod
    def setup_class(cls):
        lh.info("starting class: {} execution".format(cls.__name__))

    @classmethod
    def teardown_class(cls):
        lh.info("starting class: {} execution".format(cls.__name__))

    def setup_method(self, method):
        lh.info("starting execution of tc: {}".format(method.__name__))

    def teardown_method(self, method):
        lh.info("starting execution of tc: {}".format(method.__name__))

    def test_tc1(self):
        <tc_content>
        assert 

    def test_tc2(self):
        <tc_content>
        assert

これで、テストを実行するとき、TestClassの実行が開始されるとき、実行を開始するとき、実行を終了するとき、メソッドについても同じように、詳細をログに記録します。

それぞれの場所にある他のセットアップ手順と分解手順を追加できます。

それが役に立てば幸い!

16
Kiran Vemuri

@classmethodデコレータを追加した場合、コードは期待どおりに機能するはずです。

@classmethod 
def setup_class(cls):
    "Runs once per class"

@classmethod 
def teardown_class(cls):
    "Runs at end of class"

http://pythontesting.net/framework/pytest/pytest-xunit-style-fixtures/ を参照してください

10
Okken