2017-10-16 2 views
1

私のオートメーションフレームワークは、フィクスチャの代わりにpytest setup/teardownタイプのテストを使用します。私もクラスのいくつかのレベルがありますpytest:セットアップ/ティアダウンメソッドでパラメータ値を取得

BaseClass - 最高の、すべてのテストはそれから

FeatureClassをinhriet - メディア、プログラムに関連するすべてのテストはそれから

TestClassを継承しています - 実際のテストを保持

例のために、私はDBは、私がしたい簡易印刷

に呼び出しを変更

編集、すべてのセットアップ/ティアダウンでDBレポートを追加します。すなわち私は一般BaseClasssetup_methodがテスト用のDBエントリを作成し、teardown_methodがその結果でエントリを変更することを望みます。私は試してみましたが、実行時に現在実行中のテストの値をメソッドから抜け出すことができません。それも可能ですか?それ以外の場合はどうすればいいですか?

サンプル: (base.py中)(test_my_feature.pyで)

class Base(object): 

    test_number = 0 
    def setup_method(self, method): 
     Base.test_number += 1 
     self.logger.info(color.Blue("STARTING TEST")) 
     self.logger.info(color.Blue("Current Test: {}".format(method.__name__))) 
     self.logger.info(color.Blue("Test Number: {}".format(self.test_number))) 
     # --->here i'd like to do something with the actual test parameters<--- 
     self.logger.info("print parameters here") 

    def teardown_method(self, method): 
     self.logger.info(color.Blue("Current Test: {}".format(method.__name__))) 
     self.logger.info(color.Blue("Test Number: {}".format(self.test_number))) 
     self.logger.info(color.Blue("END OF TEST")) 

(my_feature.pyで)

class MyFeature(base.Base): 

    def setup_method(self, method): 
     # enable this feature in program 
     return True 

class TestClass(my_feature.MyFeature): 

    @pytest.mark.parametrize("fragment_length", [1,5,10])  
    def test_my_first_test(self): 
     # do stuff that is changed based on fragment_length 
     assert verify_stuff(fragment_length) 

ようにどのようにすることができテストフレームワークの基本親クラスのsetup_methodのパラメータを取得しますか?

+0

あなたは 'unittest.TestCase'を使用していますか?次に、 'setup'の値を' self'に設定し、テストでそれを取得することができます。この質問に答えるにはサンプルコードのような詳細が必要です。 – Arunmozhi

+0

@Arunmozhi私はいくつかの基本的なコードを追加しました、それは私がやろうとしていることを明確にすることを願って –

答えて

2

簡単な答え:いいえ、あなたはこれを行うことはできません。そして、はい、あなたはそれを回避することができます。


長いビット:&ティアダウンのみunittestのスタイルのテストとの互換性のために行われ、これらのunittestの風のセットアップ。彼らはpytestのフィクスチャをサポートしていません。

このため、pytestとpytestのunittestプラグインは、これらのセットアップ/ティアダウン方法のコンテキストを提供しません。 requestfunctionまたはその他のコンテキストオブジェクトがある場合は、request.getfuncargvalue('my_fixture_name')を介してフィクスチャの値を動的に取得できます。

ただし、テストメソッドオブジェクト自体(つまり、pytestのノードではありません)として、self/clsmethodがあります。

あなたが_pytest/unittest.pyプラグインの内部を見る場合は、このコードを見つけます:

class TestCaseFunction(Function): 
    _excinfo = None 

    def setup(self): 
     self._testcase = self.parent.obj(self.name) 
     self._fix_unittest_skip_decorator() 
     self._obj = getattr(self._testcase, self.name) 
     if hasattr(self._testcase, 'setup_method'): 
      self._testcase.setup_method(self._obj) 
     if hasattr(self, "_request"): 
      self._request._fillfixtures() 

まず、setup_method()が(例えばselfテストノードなど)pytestの対象から完全に分離されたと呼ばれていることに注意してください。

第2に、備品はsetup_method()の呼び出し後に準備されていることに注意してください。たとえあなたがそれらにアクセスできるとしても、彼らは準備ができません。

だから一般的に、これはやりかたをすることはできません。策略のために


、あなたは一度pytestフック/ hookwrapperを定義し、実行されてpytestノードを覚えている:

conftest.pyまたはその他のプラグイン:

import pytest 

@pytest.hookimpl(hookwrapper=True) 
def pytest_runtest_protocol(item, nextitem): 
    item.cls._item = item 
    yield 

test_me.py

import pytest 


class Base(object): 
    def setup_method(self, method): 
     length = self._item.callspec.getparam('fragment_length') 
     print(length) 


class MyFeature(Base): 
    def setup_method(self, method): 
     super().setup_method(method) 


class TestClass(MyFeature): 
    @pytest.mark.parametrize("fragment_length", [1,5,10])  
    def test_my_first_test(self, fragment_length): 
     # do stuff that is changed based on fragment_length 
     assert True # verify_stuff(fragment_length) 

また、MyFeature.setup_method() mu stは親のsuper(...).setup_method()を明らかな理由で呼び出します。

cls._itemは、各コールスペック(各パラメータの各関数呼び出し)に設定されます。必要に応じて、項目または特定のパラメータを他のグローバルな状態にすることもできます。

フィールドをitem.instanceに保存しないように注意してください。クラスのインスタンスは後で作成されるため、そのためにsetup_instance/teardown_instanceメソッドを使用する必要があります。そうでない場合、保存されたインスタンスのフィールドは保持されず、self._itemとしてsetup_method()には利用できません。ここで

が実行される:

============ test session starts ============ 
...... 
collected 3 items                                         

test_me.py::TestClass::test_my_first_test[1] 1 
PASSED 
test_me.py::TestClass::test_my_first_test[5] 5 
PASSED 
test_me.py::TestClass::test_my_first_test[10] 10 
PASSED 

============ 3 passed in 0.04 seconds ============ 
+0

詳細な返信をいただきありがとうございます、それは本当に良いpytestを理解するのに役立ちました。私はこれを試して実装しようとしています。私はあなたが明示的に 'fragment_length'を使って値を取得するのを見るので、すべてのパラメータを取得したい場合は、self._item.callspec.paramsを取得してその値を反復処理する必要がありますか? –

+1

@AvishayCohen私は確かに言うことはできませんが、おそらくはいです。ここのすべてのフィールドとメソッドは、pytestの高度なAPIの一部です。唯一の問題は、item/node/callspecがunittestのクラス/メソッドに公開されていないことでした。私はunittestとの下位互換性を意図しており、通常のpytestの使用は想定していないと思います。 –

+0

ええ。それは素晴らしい作品です! –

関連する問題