python pytest進級のfixture詳細解


前言
pytestはフィxture、fixtureはpytestの真髄と言わざるを得ません。unittestの中のsetupとteardownのように、fixtureを学ばないとpytestとunittestを使うのは違いがありません。
フィxture用途
1.テスト前後の初期化設定をします。テストデータの準備、リンクデータベース、ブラウザを開くなど、これらの操作はすべてfixtureを使って実現できます。
2.テスト用例の前置条件はfixtureで実現できます。
3.経典を支持するxunit fixture、unittestが使用するsetupとteardownのようです。
4.fixtureはunittestでは実現できない機能を実現することができます。例えば、unittestでのテストケースとテストケースの間ではパラメータとデータを伝達できません。しかし、fixtureはこの問題を解決できます。
fixture定義
fixtureは@pytest.fixture()の装飾器を通して関数を飾ります。この関数はfixtureです。実例を見てください。

# test_fixture.py
import pytest
@pytest.fixture()
def fixtureFunc():
return 'fixtureFunc'
def test_fixture(fixtureFunc):
print('    {}'.format(fixtureFunc))
if __name__=='__main__':
pytest.main(['-v', 'test_fixture.py'])
実行結果

test_fixture.py .    fixtureFunc
[100%]
========================== 1 passed in 0.02 seconds ===========================
Process finished with exit code 0
fixtureFunという関数はfixtureであり、fixture関数内部ではいくつかの初期化動作が可能です。
fixture使用
fixtureを呼び出すには3つの方法があります。
方式1
fixtureの名前は直接にテストケースのパラメータとして使われています。上の例はこのようにして、もう一つの例を見てみます。

# test_fixture.py
import pytest
@pytest.fixture()
def fixtureFunc():
return 'fixtureFunc'
def test_fixture(fixtureFunc):
print('    {}'.format(fixtureFunc))
class TestFixture(object):
def test_fixture_class(self, fixtureFunc):
print('     fixture "{}"'.format(fixtureFunc))
if __name__=='__main__':
pytest.main(['-v', 'test_fixture.py'])
方式2
各関数またはクラスの前に@pytest.mark.usefixtures('fixture')を使って飾ります。
実例

# test_fixture.py
import pytest
@pytest.fixture()
def fixtureFunc():
print('
fixture->fixtureFunc') @pytest.mark.usefixtures('fixtureFunc') def test_fixture(): print('in test_fixture') @pytest.mark.usefixtures('fixtureFunc') class TestFixture(object): def test_fixture_class(self): print('in class with text_fixture_class') if __name__=='__main__': pytest.main(['-v', 'test_fixture.py'])
方式3
fixtureを指定するパラメータautuse=Trueは、各テスト用例によって自動的にfixtureを呼び出すことができます(ここでは正確ではありません。fixtureの作用範囲にも関連していますので、ここではデフォルトは関数レベルです。後にfixtureの役割範囲を具体的に説明します)
実例

# test_fixture.py
import pytest
@pytest.fixture(autouse=True)
def fixtureFunc():
print('
fixture->fixtureFunc') def test_fixture(): print('in test_fixture') class TestFixture(object): def test_fixture_class(self): print('in class with text_fixture_class') if __name__=='__main__': pytest.main(['-v', 'test_fixture.py'])
結果

fixture->fixtureFunc
.in test_fixture
fixture->fixtureFunc
.in class with text_fixture_class
[100%]
========================== 2 passed in 0.04 seconds ===========================
結果から、各テストケースの実行前に自動的にfixtureが実行されていることが分かります。
結び目
上の方法をマスターすれば、フィxtureが使えますが、このいくつかの方法には違いがありますか?実際に私が書いたコードからも分かりますが、テストケースがフィxtureで返されるパラメータを使う必要があるなら、後の2つの方法では戻りのパラメータは使えません。フィxtureで返したデータはデフォルトでフィxtureの名前に保存されていますので、最初の方法でのみフィxtureの戻り値を呼び出すことができます。理論は永遠に理論で、文章の古い鉄は自分で試してみましょう。)
fixturの作用範囲
上のすべてのインスタンスはデフォルトでは関数レベルですので、テスト関数はフィxtureを呼び出すとテスト関数が実行される前にfixtureを指定します。作用範囲というと、fixtureの第二パラメータscopeパラメータと言わざるを得ません。
scopeパラメータはsession、module、class、functionであることができます。デフォルトはfunctionです
1.セッションレベル(通常はこのレベルはconft.pyファイルと結合して使用されますので、後でconft.pyファイルについて話します。)
2.moduleモジュールレベル:モジュール内のすべての用例を実行する前に一回moduleレベルのfixtureを実行します。
3.クラスクラスクラス:各クラスの実行前に一回のクラスのfixtureを実行します。
4.function:前の例ではすでに述べましたが、このデフォルトはデフォルトのモードであり、関数レベルのものであり、各テストケースが実行される前に一回functionレベルのfixtureを実行します。
次に私達は具体的な例を通して、fixtureの作用範囲を見ます。

# test_fixture.py
import pytest
@pytest.fixture(scope='module', autouse=True)
def module_fixture():
print('
-----------------') print(' module fixture') print('-----------------') @pytest.fixture(scope='class') def class_fixture(): print('
-----------------') print(' class fixture') print('-------------------') @pytest.fixture(scope='function', autouse=True) def func_fixture(): print('
-----------------') print(' function fixture') print('-------------------') def test_1(): print('
test1') @pytest.mark.usefixtures('class_fixture') class TestFixture1(object): def test_2(self): print('
class1 test2') def test_3(self): print('
class1 test3') @pytest.mark.usefixtures('class_fixture') class TestFixture2(object): def test_4(self): print('
class2 test4') def test_5(self): print('
class2 test5') if __name__=='__main__': pytest.main(['-v', '--setup-show', 'test_fixture.py'])
実行結果
私たちはcdmでsetup-showを実行します。具体的なsetupとteardoenの順番を確認できます。

test_fixture.py 
  SETUP  M module_fixture
    SETUP  F func_fixture
-----------------
  module fixture
-----------------
-----------------
  function fixture
-------------------
    test_fixture.py::test_1 (fixtures used: func_fixture, module_fixture).
   test1
    TEARDOWN F func_fixture
   SETUP  C class_fixture
    SETUP  F func_fixture
-----------------
  class fixture
-------------------
-----------------
  function fixture
-------------------
    test_fixture.py::TestFixture1::test_2 (fixtures used: class_fixture, func_fixture, module_fixture).
  class1   test2
    TEARDOWN F func_fixture
    SETUP  F func_fixture
-----------------
  function fixture
-------------------
    test_fixture.py::TestFixture1::test_3 (fixtures used: class_fixture, func_fixture, module_fixture).
  class1   test3

    TEARDOWN F func_fixture
   TEARDOWN C class_fixture
   SETUP  C class_fixture
    SETUP  F func_fixture
-----------------
  class fixture
-------------------

-----------------
  function fixture
-------------------
 test_fixture.py::TestFixture2::test_4 (fixtures used: class_fixture, func_fixture, module_fixture).
  class2   test4

    TEARDOWN F func_fixture
    SETUP  F func_fixture
-----------------
  function fixture
-------------------
 test_fixture.py::TestFixture2::test_5 (fixtures used: class_fixture, func_fixture, module_fixture).
  class2   test5

    TEARDOWN F func_fixture
   TEARDOWN C class_fixture
  TEARDOWN M module_fixture

========================== 5 passed in 0.05 seconds ===========================
モジュール全体が一回だけmoduleレベルのfixtureを実行しています。各クラスはそれぞれ一回のクラスのfixtureを実行しています。各関数は前に一回のfunctionレベルのfixtureを実行しました。
fixtureはteardownを実現します。
実際には、前のすべての例は、テストケースの実行前の準備作業だけですが、用例実行後はどのように環境整理の仕事を実現しますか?これはどうしてもyieldキーワードと言わざるを得ません。みんなより多かれ少なかれこのキーワードを知っています。彼の役割は実はreturnと同じです。データを调节者に返してもいいです。唯一の違いは掉関数実行がyieldに会ったら実行を停止します。続いてコールセンターの関数を実行します。呼び出した関数が実行されたら、引き続きyieldキーの後ろのコードを実行します。以下の例を見て、teardown機能の実現方法を調べてみます。

import pytest
from selenium import webdriver
import time
@pytest.fixture()
def fixtureFunc():
  '''           '''
driver = webdriver.Firefox()
yield driver
driver.quit()
def test_search(fixtureFunc):
'''      ,  pytest           '''
driver = fixtureFunc
driver.get('http://www.baidu.com')
driver.find_element_by_id('kw').send_keys('pytest')
driver.find_element_by_id('su').click()
time.sleep(3)
source = driver.page_source
assert 'pytest' in source
if __name__=='__main__':
pytest.main(['--setup-show', 'test_fixture.py'])
この例はまずブラウザを開き、テストケースを実行し、最後にブラウザを閉じます。みんな試してもいいですyieldを通して、用例実行後のteardown機能を実現しました。
締め括りをつける
1.fixtureはどうやって定義しますか?
2.fixtureの使い方
3.fixtureの作用範囲
4.fixtureはyieldでteardown機能を実現する。
最後に一言を言います。実際の仕事ではaut=Trueというパラメータをできるだけ使わないと、思わぬ結果を招くかもしれません。一番よく使われているのはやはり伝達パラメータによって一番いいです。
以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。