国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Python - pytest自動化測試fixture的作用域實例化順序及可用性

pytest自動化測試fixture的作用域實例化順序及可用性

2022-01-21 00:07愛測試的高胖胖 Python

這篇文章主要介紹了pytest自動化測試中fixture的作用域、實例化順序及可用性的詳解示例有需要的朋友可以借鑒參考下,希望能夠有所幫助

1. fixture的作用域

1.1 scope

通過前面文章的介紹,我們知道@pytest.fixture()有一個scope參數,并且有五個作用域級別,這五個作用域級別的說明總結如下:

注意:fixture是在測試首次請求時創建的,并基于它們的作用域被銷毀。

scope 說明
function 默認值,函數或方法級別被調用,當函數執行結束后,fixture則被銷毀
class 類級別調用一次,當類中的最后一個測試函數執行結束后,fixture則被銷毀
module 模塊級別(每一個.py文件)調用一次,當模塊中最后一個測試函數執行結束后,fixture則被銷毀
package 包(一個文件夾下的.py文件)級別調用一次,當包中最后一個測試函數執行結束后,fixture則被銷毀
session 多個文件調用一次,當多文件中最后一個測試函數執行結束后,fixture則被銷毀

單看說明,還是不太好理解的,所以下面我們通過示例來了解一下scope的用法。

示例1:

1.function:

演示代碼:

import pytest
@pytest.fixture()
def login():
  print('登陸操作')
  yield
  print('注銷操作')
class TestClass:
  def test_case1(self,login):
      print("TestClass:test_case1")

  def test_case2(self):
      print("TestClass:test_case2")
      

運行結果:

pytest自動化測試fixture的作用域實例化順序及可用性

說明:

演示代碼中,我們定義了一個fixture函數――login 和兩個測試函數 test_case1test_case2

裝飾器@pytest.fixture()沒有指定scope參數,因此使用默認值:function

test_case1test_case2TestClass類中,且test_case1調用了logintest_case2未調用。

通過運行結果,我們可以看出來,scope=function的fixture――login,只在調用了它的test_case1這個測試函數前后執行。test_case2未執行。

2.class:

演示代碼:

import pytest
@pytest.fixture(scope='class')   #名為login的fixture,完成登陸和注冊操作
def login():
  print('登陸操作')
  yield
  print('注銷操作')
class TestClass1:
  def test_case1(self,login):  #調用了login
      print("TestClass1:test_case1")
  def test_case2(self):
      print("TestClass1:test_case2")
class TestClass2:
  def test_case1(self):
      print("TestClass2:test_case1")
  def test_case2(self,login):  #調用了login
      print("TestClass2:test_case2")
@pytest.mark.usefixtures("login")  #TestClass3這個類,使用usefixtures調用了login
class TestClass3:
  def test_case1(self):
      print("TestClass3:test_case1")
  def test_case2(self):
      print("TestClass3:test_case2")

運行結果:

pytest自動化測試fixture的作用域實例化順序及可用性

說明:

演示代碼中我們定義了一個fixture――login;三個測試類――TestClass1TestClass2TestClass3,這個三個測試類中都定了兩個測試函數――test_case1test_case2

對fixture函數我們聲明了其作用域――scope='class'
TestClass1中,只有test_case1調用了login
TestClass2中,只有test_case1調用了login
TestClass3,我們使用@pytest.mark.usefixtures("login"),讓整個類調用了login

查看運行結果我們可以發現:
TestClass1中,test_case1運行前有”登陸操作“打印,并在test_case2執行后有”注銷操作“顯打印。
TestClass2中,只有test_case2運行前有”登陸操作“打印,并在test_case2執行后有”注銷操作“打印。而test_case1執行前后并無任何數據打印。
TestClass3則與Testclass1執行后數據顯示一致。

TestClass1TestClass2結果的不同是由什么原因造成的呢?
官方文檔在介紹fixture的scope的時候,有這樣一句話,上文中也有提到:fixture是在測試首次請求時創建的,并基于它們的作用域被銷毀。(Fixtures are created when first requested by a test, and are destroyed based on their scope。)
對于TestClass1test_case1調用了login,因此會在test_case1執行的時候,創建login,并在其執行之前打印了”登陸操作“。又根據login的scope――class,在TestClass1的最后一個測試函數test_case2執行后,根據login的功能打印”注銷操作“,并銷毀login
對于TestClass2login是由test_case2調用的,而test_case1test_case2先執行,所以test_case1執行的時候login還未被調用,fixture未被創建。直到執行test_case2時,login才被創建并進行了對應的操作。
后面其他類型的作用域示例中將不會在演示此種情況。

3.module:

演示代碼:

import pytest
@pytest.fixture(scope='module')   #名為login的fixture,完成登陸和注冊操作
def login():
  print('登陸操作')
  yield
  print('注銷操作')
@pytest.mark.usefixtures("login")
class TestClass1:
  def test_case1(self):
      print("TestClass1:test_case1")
  def test_case2(self):
      print("TestClass1:test_case2")
class TestClass2:
  def test_case1(self):
      print("TestClass2:test_case1")
  def test_case2(self):
      print("TestClass2:test_case2")


運行結果:

pytest自動化測試fixture的作用域實例化順序及可用性

說明:

演示代碼中,我們定義了:
一個fixture――login(),并且聲明其scope=”module“
兩個測試類――TestClass1TestClass2
兩個測試類中分別定義了兩個測試函數――test_case1test_case2
TestClass1使用@pytest.mark.usefixtures("login")的方法,調用了login()

運行結果顯示:
執行時,自第一個測試函數TestClass1中的test_case1調用login()時,該fixture被創建,并且按照login()實現的功能打印"登陸操作",并在當前模塊中(一個.py文件)最后一個測試函數TestClass2中的test_case2執行結束后,按照login()實現的功能打印"注銷操作",然后被銷毀。

4.package:

演示代碼:

首先看一下測試包目錄,新增一個conftest.py。里面所有的模塊都是上面的演示代碼。修改這些模塊里代碼,注釋調feature函數,刪掉調用即可。

pytest自動化測試fixture的作用域實例化順序及可用性

conftest.py

import pytest
@pytest.fixture(scope='package',autouse=True)   #名為login的fixture,完成登陸和注冊操作
def login():
  print('登陸操作')
  yield
  print('注銷操作')
  

使用命令行運行:

pytest自動化測試fixture的作用域實例化順序及可用性

運行結果:

pytest自動化測試fixture的作用域實例化順序及可用性

說明:
conftest.py中聲明了一個fixture――login(),并且設置scope='package'autouse=True

使用命令行方式運行test_scope這個測試包中的所有模塊。查看運行結果,在test_scope中第一個測試函數調用login()的時候,login創建,并按照功能打印”登陸操作“。在test_scope中最后一個測試函數運行結束后,按照login()功能打印出”注銷操作“,并銷毀login()

5.session:

使用package的演示代碼,需改conftest.pylogin()scope='session',然后我們直接在終端中使用命令行運行多個文件。

運行以下命令:

pytest自動化測試fixture的作用域實例化順序及可用性

運行結果:

pytest自動化測試fixture的作用域實例化順序及可用性

說明:

使用命令行方式運行test_scope這個測試包中的test_class.py和test_function.py。查看運行結果,在test_class.py中第一個測試函數調用login()的時候,login創建,并按照功能打印”登陸操作“。在test_function.py中最后一個測試函數運行結束后,按照login()功能打印出”注銷操作“,并銷毀login()

1.2 動態作用域(Dynamic scope)

在某些情況下,我希望在不更改代碼的情況下更改feature的作用域。pytest的從5.2版本開始,提供了動態作用域的方法,來解決這種情況。

通過官方文檔的說明,我們了解到,可以將一個可調用對象傳遞給scope來實現動態作用域。這個可調用對象必須滿足以下三個條件:

1.這個可調用對象返回類型需是string,且必須是有效的scope級別,即只能返回"function""class""module""package""session"中的一個。
2.在fixture定義期間,這個可調用對象只能被執行一次,不能被多次調用。
3.這個可調用對象定義的時候,必須使用fixture_nameconfig作為參數。

下面通過示例給大家演示以下用法。

示例2:

演示代碼:

import pytest
def dynamic_fixture_scope(fixture_name,config):
  if config.getoption("-k",None):   
      return "function"
  return "class"
@pytest.fixture(scope=dynamic_fixture_scope,autouse=True)
def login():
  print('登陸操作')
  yield
  print('注銷操作')
class TestClass1:
  def test_A(self):
      print("這是TestClass1:test_A")
  def test_B(self):
      print("這是TestClass1:test_B")
class TestClass2:
  def test_A(self):
      print("這是TestClass2:test_A")

說明:

dynamic_fixture_scope:用來管理fixture的作用域,這個函數按照pytest官方文檔的要求,帶有fixture_nameconfig兩個關鍵字作為參數,并且實現下述功能:

1.當用命令行運行測試時,運行命令中帶有‘-k'參數,則被調的fixture函數的作用域為"function"

2.其余情況下,被調的fixture的函數為"class"

login:一個使用動態作用域方法的fixture,其scope=dynamic_fixture_scope。為了方便演示,autouse也被設置為True

下面我們分兩種情況來運行看看:

1.帶參數-k運行

運行命令:我們只運行測試名稱中包含test_A的測試函數。

pytest -vs -k 'test_A' test_dynamicscope.py

運行結果:

pytest自動化測試fixture的作用域實例化順序及可用性

通過運行結果可以看到,當命令行中出現-k參數的時候,loginscope確實是function級別的。兩個被選中的測試函數分別在不同的測試類中,但是都調用了login

2.無參數-k運行

運行命令:我們不帶參數-k運行。

pytest -vs test_dynamicscope.py 

運行結果:

pytest自動化測試fixture的作用域實例化順序及可用性

通過運行結果可以看到,無-k參數的時候,loginscope確實是class級別的。

 

2. fixture的實例化順序

根據官方文檔,我們了解到影響fixture實例化順序的三個因素是:

1. 作用域(scope)
2. 依賴項
3. 自動調用(autouse)

而fixture名稱、測試函數名稱以及定義它們的位置一般都不會影響執行順序。

下面介紹一下這個三個因素是如何影響實例化順序的。

2.1 作用域級別高的fixture先執行

我們直接使用官方文檔提供的示例來說明。

示例3:

演示代碼:

import pytest
@pytest.fixture(scope="session")
def order():
  return []
@pytest.fixture
def func(order):
  order.append("function")
@pytest.fixture(scope="class")
def cls(order):
  order.append("class")
@pytest.fixture(scope="module")
def mod(order):
  order.append("module")
@pytest.fixture(scope="package")
def pack(order):
  order.append("package")
@pytest.fixture(scope="session")
def sess(order):
  order.append("session")
class TestClass:
  def test_order(self, func, cls, mod, pack, sess, order):
      assert order == ["session", "package", "module", "class", "function"]

運行結果:

pytest自動化測試fixture的作用域實例化順序及可用性

說明:
演示代碼中我們定義了:
六個fixture函數:

order:scope為session級別,返回一個空list。func: 調用了order,scope為默認的function級別,并實現向order返回的列表中插入”function“的操作。cls:調用了order,scope為class級別,并實現向order返回的列表中插入”class“的操作。mod:調用了order,scope為module級別,并實現向order返回的列表中插入”module“的操作。pack:調用了order,scope為package級別,并實現向order返回的列表中插入”package“的操作。sess:調用了order,scope為session級別,并實現向order返回的列表中插入”session“的操作。

一個測試函數:
test_order:主要目的是通過list中元素的順序來判斷是否按照預想的順序執行fixture。

根據運行結果顯示,測試斷言通過,也就是fixture的執行順序是按照我們預期的scope的級別由高到低去執行的。

test_order調用fixture的順序是func, cls, mod, pack, sess, order,而實際執行的順序是order, sess, pack, mod, cls, func。由此可見,我們在調用時定義的順序不會影響到fixture的實際執行順序的。

官網執行順序圖:

pytest自動化測試fixture的作用域實例化順序及可用性

其中sessorder的scope都是session級別的,但是因為order是sess的依賴項,所以會先調用order,這個一點正好我們下面要說明。

2.2 fixture函數的依賴項先執行

前面文章中有說過,fixture函數是可以調用另外一個fixture函數的。在執行的時候,也是先執行調用的那個fixture函數。舉了例子,fixture a 調用了fixture b,當測試函數調用fixture a的時候,會先去執行fixture b 然后再執行fixture a,最后執行測試函數。

這是因為fixture b 是fixture a 的依賴項,fixture a 可能會需要fixture b提供一些條件才能正常被執行。

下面我們來看一下官方文檔提供的一個例子,

示例4:

演示代碼:

import pytest
@pytest.fixture
def order():
  return []
@pytest.fixture
def a(order):
  order.append("a")
@pytest.fixture
def b(a, order):
  order.append("b")
@pytest.fixture
def c(a, b, order):
  order.append("c")
@pytest.fixture
def d(c, b, order):
  order.append("d")
@pytest.fixture
def e(d, b, order):
  order.append("e")
@pytest.fixture
def f(e, order):
  order.append("f")
@pytest.fixture
def g(f, c, order):
  order.append("g")
def test_order(g, order):
  assert order == ["a", "b", "c", "d", "e", "f", "g"]

運行結果:

pytest自動化測試fixture的作用域實例化順序及可用性

說明:

演示代碼中定義了八個fixture函數和一個測試函數,其中:
fixture函數有:ordeabcdefg
測試函數有:test_order

a調用了order
b調用了a, order
c調用了a, b, order
d調用了c, b, order
f調用了e, order
g調用了f, c, order
test_order調用了gorder

我們來整理以上所有函數的依賴關系,他們之間的依賴關系如圖所示:

pytest自動化測試fixture的作用域實例化順序及可用性

之前文章也有說過,在同一次測試執行過程中,fixture是可以被多次調用的,但是不會被多次執行。執行一次后,fixture的實例對象和返回值會存在緩存中,下次再被調用的時候是直接從緩存中獲取的。

所以上面的順序我們可以再簡化一下:

pytest自動化測試fixture的作用域實例化順序及可用性

執行完所有依賴的fixture函數后,我們得到的order的結果為:['a','b','c','d','e'],因此測試斷言通過。

2.3 自動使用的fixture在其作用域內首先執行

根據官方文檔的說明,我們可以得到一下兩點重要內容:

1.當測試函數調用的fixture的作用域級別都一樣,那么會首先調用自動使用的fixture。

示例5:

import pytest
@pytest.fixture
def order():
  return []
@pytest.fixture
def func(order):
  order.append("function")
@pytest.fixture(autouse=True) #修改cls為自動使用fixture
def cls(order):
  order.append("class")
@pytest.fixture
def mod(order):
  order.append("module")
@pytest.fixture
def pack(order):
  order.append("package")
@pytest.fixture
def sess(order):
  order.append("session")
class TestClass:
  def test_order(self, func, cls, mod, pack, sess, order):
      print(order)
      assert order == ["session", "package", "module", "class", "function"]

運行結果:

pytest自動化測試fixture的作用域實例化順序及可用性

說明:

我們把示例3的代碼拿過來修改一下,把所有fixture的scope都改為function級別,并且對cls試著autouse=True。
test_order請求fixture的順序是:func, cls, mod, pack, sess

當scope級別一樣的時候,且無依賴關系的時候,fixture的執行順序應該與調用順序一致,也應該是func, cls, mod, pack, sess。但是實際運行的結果卻是['class', 'function', 'module', 'package', 'session']。由此可以判斷出,在scope一致且無依賴的情況下,自動執行的fixture是最先被執行的。

2.對一個autouse的fixture A來說,若調用了非autouse的fixture B,那么對于調用了fixture A的測試函數來說,fixture B也相當于是autouse的。

我們再來看一下官方給的一個示例。

示例6:

演示代碼:

import pytest
@pytest.fixture
def order():
  return []
@pytest.fixture
def a(order):
  order.append("a")
@pytest.fixture
def b(a, order):
  order.append("b")
@pytest.fixture(autouse=True)
def c(b, order):
  order.append("c")
@pytest.fixture
def d(b, order):
  order.append("d")
@pytest.fixture
def e(d, order):
  order.append("e")
@pytest.fixture
def f(e, order):
  order.append("f")
@pytest.fixture
def g(f, c, order):
  order.append("g")
def test_order_and_g(g, order):
  assert order == ["a", "b", "c", "d", "e", "f", "g"]

說明:

演示代碼中定義了八個fixture函數和一個測試函數,其中:
fixture函數有:ordeabcdefg
測試函數有:test_order

a調用了order
b調用了a, order
c調用了 b, order,且是自動使用fixture;
d調用了 b, order
f調用了e, order
g調用了f, c, order
test_order調用了gorder

若c是非自動使用的fixture,代碼中fixture的一個執行順序是什么樣的呢?

下圖是運行結果:

pytest自動化測試fixture的作用域實例化順序及可用性

根據上面的運行結果和下面的順序圖,我們可以看到,除了g調用了c之外,其他函數都沒有調用c,而g也調用了f,所以現在還不清楚c應該在d、e、f之前還是之后執行。對c來說他只需在b之后、g之前執行即可。而實際運行結果,c是在d、e、f之后和g之前執行的。

對于pytest來說,fixture的執行順序就是不明確,這種情況很可能會影響測試函數的執行行為,影響了測試結果。

pytest自動化測試fixture的作用域實例化順序及可用性

所以,我們需要明確fixture的執行順序。

當我們使c為自動使用fixture時,這個順序又會發生什么變化呢?

下圖為運行結果:

pytest自動化測試fixture的作用域實例化順序及可用性

根據上圖的運行結果和下圖的順序圖,我們可以看出來,當自動使用c后,它的執行優先級就比d要高,所以可以保證c是在d之前執行的。這樣使執行順序明確了。

pytest自動化測試fixture的作用域實例化順序及可用性

當c是自動使用的fixture后,根據fixture函數的依賴項先執行這一規則,c所依賴的b、b所依賴的a和a所依賴的order都會被執行。這樣對于調用了c的g來說,order、a、b也相當于是自動使用的fixture了,但是當有其他fixture調用order、a、b時,order、a、b仍然保持自己的特性。

 

本節總結

我們來總結一下fixture實例化順序的一個規則:

1.fixture的scope級別越高,那么它執行的優先級越高。優先級為:session>package>module>class>function

2.fixture如果存在依賴項,那么它所依賴的fixture函數會先被執行。

3.同scope級別fixture中,自動使用的fixture會最先執行;若該fixture存在依賴項,則對于調用了fixture的測試函數來說,這些依賴項也可以看做是自動使用的。

4.我們在編碼的時候最好可以依照以上規則為pytest提供一個清晰的fixture執行順序,以免影響測試函數的行為和測試結果。

 

3. fixture的可用性

對于測試函數來說,能夠調用那些fixture,是由fixture定義的位置決定。

1.當fixture定義在一個測試類中時,只有該類中的測試函數可調用此fixture,其他測試函數無法調用該fixture。當測試函數在模塊的全局范圍內定,則模塊下的所有測試函數都可以調用它。該特點與全局變量和局部變量相似。

示例7:

演示代碼:

import pytest
class TestClass1:
  @pytest.fixture()
  def login(self):
      print("login")
  def test_case1(self,login):
      print("TestClass1::test_case1")
class TestClass2:
  def test_case2(self,login):
      print("test_case2")

運行結果:

pytest自動化測試fixture的作用域實例化順序及可用性

說明:

演示代碼中定義了兩個測試類:TestClass1TestClass2
TestClass1中定義了一個fixture――login,和測試函數test_case1test_case1有調用login
TestClass1中定義了一個測試函數test_case2test_case2有調用login

通過運行結果我們可以看到,與login在同一測試類中的test_case1成功調用了login,但是TestClass2test_case2調用login的時候報錯了,報錯原因:未發現fixture函數“login”

2.conftest.py中定義的fixture,可以被同目錄下的所有模塊中定義的測試函數調用。

示例8:

演示代碼:

test_availability/conftest.py:

import pytest
@pytest.fixture()
def login():
  print("login")
  

test_availability/test_availability.py:

class TestClass1:
  def test_case1(self,login):
      print("TestClass1::test_case1")
class TestClass2:
  def test_case2(self,login):
      print("test_case2")

運行結果:

pytest自動化測試fixture的作用域實例化順序及可用性

說明:

我們在test_availability目錄下創建了一個conftest.py,并且定義了一個fixture――login
在test_availability.py中,我們定義了兩個測試函數test_case1test_case1,兩個測試函數都調用了login

查看運行結果,測試函數都成功調用了login

3.如果安裝的第三方插件提供了fixture,任何測試函數都可以正常使用,無需考慮位置因素。

文末說明:
以上內容是我在閱讀pytest官方文檔后,依照個人理解進行整理。內容可能會有理解錯誤之處,歡迎大家留言指正。謝謝

更多關于fixture作用域實例化順序及可用性的資料請關注服務器之家其它相關文章!

原文鏈接:https://blog.csdn.net/gjj920318/article/details/118704453

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 国产一区日韩在线 | 黄视频网站免费观看 | 九九热在线视频 | 懂色av中文字幕一区二区三区 | 日韩精品专区 | 成人精品视频 | 日韩av免费在线观看 | 国产日韩精品在线观看 | www久久久久 | 中文字幕 亚洲一区 | 久久精品亚洲 | 爱爱h视频 | 一大道一二三区不卡 | jizz国产| 99久久精品国产一区二区三区 | 国产高清一区二区 | 一区二区不卡视频 | 小川阿佐美88av在线播放 | 日韩大片在线观看 | 色狠狠综合天天综合综合 | 亚洲精品永久免费 | 久久综合电影 | 91精品国产成人 | 久草视频国产 | 欧美污污 | 特黄特黄aaaa级毛片免费看 | 丁香婷婷综合激情五月色 | 亚洲精品一区二区三区 | 91国产视频在线 | 亚洲精品成人天堂一二三 | 欧美一区二区三区啪啪 | 欧美1区2区3区 | 成人精品一区二区三区 | 一本久久a久久精品亚洲 | 亚洲一区欧美 | 国产高清免费 | 毛片av在线播放 | 国产一区二 | 韩日中文字幕 | 福利片在线免费观看 | 一区二区三区在线免费观看 |