Pytest中fixture的作用範圍(六)

  • 2019 年 10 月 7 日
  • 筆記

前面介紹了fixture的參數化,以及conftest.py的系列知識,本文章主要總結fixture的參數scope,通過它可以指定fixture的作用範圍。scope的參數主要應用於控制fixture執行配置和銷毀邏輯的頻率。在scope的參數中主要有四個值可以選擇,分別是function(函數級別),class(類級別).module(模組級別),session(會話級別),它的默認值是函數級別。下面依據各個案例來說明該參數的實際應用。

先來看函數級別,也就是說函數級別中,每個測試函數只需要執行一次,配置程式碼在測試用例運行前執行,銷毀程式碼是在測試用例運行之後執行。見案例程式碼:

#!/usr/bin/python3  #coding:utf-8  import  pytest    @pytest.fixture(scope='function')  def api():      print('開始執行')      yield      print('結束執行')      def test_login_001(api):      assert  1==1

該fixture僅僅是函數級別的應用,不會應用於其他的方面,見執行後的結果資訊:

platform darwin -- Python 3.7.4, pytest-4.0.2, py-1.8.0, pluggy-0.12.0  rootdir: /Applications/code/stack/study/xunit/scope, inifile:  plugins: html-1.22.0, allure-adaptor-1.7.10, metadata-1.8.0  collected 1 item    test_001.py          SETUP    F api          test_001.py::test_login_001 (fixtures used: api).          TEARDOWN F api

下來看類級別的,類級別的主要指的是每個測試類需要運行一次,無論測試類裡面有多少個測試方法,都會被執行到並且共享fixture,見案例程式碼:

#!/usr/bin/python3  #coding:utf-8  import  pytest    @pytest.fixture(scope='class')  def api():      print('開始執行')      yield      print('結束執行')        class TestLogin(object):      def test_login_001(self,api):          assert  1==1      def test_login_002(self):          assert  1==1

見執行後的結果資訊:

platform darwin -- Python 3.7.4, pytest-4.0.2, py-1.8.0, pluggy-0.12.0  rootdir: /Applications/code/stack/study/xunit/scope, inifile:  plugins: html-1.22.0, allure-adaptor-1.7.10, metadata-1.8.0  collected 2 items    test_001.py        SETUP    C api          test_001.py::TestLogin::test_login_001 (fixtures used: api).          test_001.py::TestLogin::test_login_002 (fixtures used: api).        TEARDOWN C api

來來看模組級別的,在模組級別的fixture每個模組只需要執行一次,無論模組裡面有多少個測試函數,類方法,都可以共享這個fixture,見案例程式碼:

import  pytest    @pytest.fixture(scope='module')  def api():      print('開始執行')      yield      print('結束執行')    def test_login_001(api):      assert  1==1  class TestApi(object):      def test_api_001(self,api):          assert  1==1

見執行後的輸出資訊:

platform darwin -- Python 3.7.4, pytest-4.0.2, py-1.8.0, pluggy-0.12.0  rootdir: /Applications/code/stack/study/xunit/scope, inifile:  plugins: html-1.22.0, allure-adaptor-1.7.10, metadata-1.8.0  collected 2 items    test_001.py      SETUP    M api          test_001.py::test_login_001 (fixtures used: api).          test_001.py::TestApi::test_api_001 (fixtures used: api).      TEARDOWN M api

是否存在這樣的一個疑問,函數級別的是否可以應用在類級別,類級別的是否可以應用於函數級別了,見測試程式碼:

import  pytest    @pytest.fixture(scope='function')  def api():      print('開始執行')      yield      print('結束執行')    def test_login_001(api):      assert  1==1  class TestApi(object):      def test_api_001(self,api):          assert  1==1

見輸出的資訊:

platform darwin -- Python 3.7.4, pytest-4.0.2, py-1.8.0, pluggy-0.12.0  rootdir: /Applications/code/stack/study/xunit/scope, inifile:  plugins: html-1.22.0, allure-adaptor-1.7.10, metadata-1.8.0  collected 2 items    test_001.py          SETUP    F api          test_001.py::test_login_001 (fixtures used: api).          TEARDOWN F api          SETUP    F api          test_001.py::TestApi::test_api_001 (fixtures used: api).          TEARDOWN F api

最後一個是會話級別的,會話級別的fixture每次會話只需要運行一次,一次pytest會話中的所有測試函數,方法都可以共享該fixture,見案例程式碼:

#!/usr/bin/python3  #coding:utf-8  import  pytest    @pytest.fixture(autouse=True,scope='session')  def wuya():      print('start')      yield      print('end')

見測試的程式碼:

#!/usr/bin/python3  #coding:utf-8  import  pytest    def test_login_001():      assert  1==1  class TestApi(object):      def test_api_001(self):          assert  1==1

見執行後輸出的結果資訊:

platform darwin -- Python 3.7.4, pytest-4.0.2, py-1.8.0, pluggy-0.12.0  rootdir: /Applications/code/stack/study/xunit/scope, inifile:  plugins: html-1.22.0, allure-adaptor-1.7.10, metadata-1.8.0  collected 2 items    test_001.py  SETUP    S wuya          test_001.py::test_login_001 (fixtures used: wuya).          test_001.py::TestApi::test_api_001 (fixtures used: wuya).  TEARDOWN S wuya

在pytest中也可以使用userfixture指定多個fixture,這樣來標記測試函數或者測試的類,使用usefixture,需要在一個參數中指定一個或者多個fixture字元串,這樣的一個場景在特定的場景下還是可以的,見案例的測試程式碼:

#!/usr/bin/python3  #coding:utf-8  import  pytest    @pytest.fixture()  def api():      return 1  @pytest.fixture()  def init():      print('start')      yield      print('end')    @pytest.mark.usefixtures('api','init')  def test_login_001(api):      assert  api==1

見執行後輸出的資訊:

platform darwin -- Python 3.7.4, pytest-4.0.2, py-1.8.0, pluggy-0.12.0  rootdir: /Applications/code/stack/study/xunit/scope, inifile:  plugins: html-1.22.0, allure-adaptor-1.7.10, metadata-1.8.0  collected 1 item    test_001.py          SETUP    F api          SETUP    F init          test_001.py::test_login_001 (fixtures used: api, init).          TEARDOWN F init          TEARDOWN F api

在如上的結果資訊中,就可以看到,測試函數共享了兩個fixture。

在前面使用fixture的時候說到了autouse的選項,也應該看到,如果不使用該選項,每次共享fixture都需要指定,但是使用了它後就不需要指定了,那麼標準的說法應該是:依據選項autouse=True,使作用域內的測試函數都執行該fixture,這與那些需要多次執行,但不依賴任何的狀態或者外部數據的程式碼配合的比較好。針對如上的程式碼修改,見修改後的源碼:

#!/usr/bin/python3  #coding:utf-8  import  pytest    @pytest.fixture(autouse=True)  def api():      return 1  @pytest.fixture(autouse=True)  def init():      print('start')      yield      print('end')      def test_login_001(api):      assert  api==1

見執行後輸出的結果資訊:

platform darwin -- Python 3.7.4, pytest-4.0.2, py-1.8.0, pluggy-0.12.0  rootdir: /Applications/code/stack/study/xunit/scope, inifile:  plugins: html-1.22.0, allure-adaptor-1.7.10, metadata-1.8.0  collected 1 item    test_001.py          SETUP    F api          SETUP    F init          test_001.py::test_login_001 (fixtures used: api, init).          TEARDOWN F init          TEARDOWN F api

Tags: