fixture (使用pytest.fixture 替換使用setup, yield替換使用teardown,並將前置條件寫進conftest.py文件)



fixture   (是pytest特有的功能)           

# fixture 官方文檔::        https://docs.pytest.org/en/stable/fixture.html       

 

1、fixture特點:
必須用pytest.fixture裝飾器裝飾;fixture有明確的名字,在其他函數(function,默認),模塊(module),類(class)或整個工程(session)調用它時會被激活,pytest自己去查找使用;

可以調用其他的fixture;
可以和測試函數寫在同一個文件里;
fixture也可作為是預置項,在測試用例執行之前需要去配置它,執行完后去釋放它;
fixture還提供了參數化功能,根據配置和不同組件來選擇不同的參數;


查看fixture幫助源碼:

fixture(scope="function", params=None, autouse=False, ids=None, name=None):
"""使用裝飾器標記fixture的功能 可以使用此裝飾器(帶或不帶參數)來定義fixture功能。 fixture功能會在運行測試之前調用它:test模塊或類可以使用pytest.mark.usefixtures(fixturename標記) 測試功能可以直接使用fixture名稱作為輸入參數,在這種情況下,夾具實例從fixture返回功能將被注入。 """ :scope: scope 有四個級別參數 "function" (默認), "class", "module" or "session". :params: 一個可選的參數列表,它將導致多個參數調用fixture功能和所有測試使用它 :autouse: 如果為True,則為所有測試激活fixture func 可以看到它。 如果為False(默認值)則顯式需要參考來激活fixture :ids: 每個字符串id的列表,每個字符串對應於params 這樣他們就是測試ID的一部分。 如果沒有提供ID它們將從params自動生成 :name: fixture的名稱。 這默認為裝飾函數的名稱。 如果fixture在定義它的同一模塊中使用,夾具的功能名稱將被請求夾具的功能arg遮蔽; 解決這個問題的一種方法是將裝飾函數命名。“fixture_ <fixturename>”然后使用”@ pytest.fixture(name ='<fixturename>')“”。

 

根據上述fixture介紹的總結:

fixture的參數scope可傳遞的4種類型:

function:每個函數及方法都運行,默認是function的scope
class:每個測試類class之前執行一次
module:每個.py文件 只運行一次
session:每個session只運行一次(即可以跨.py文件運行)

 

2、使用firture相對於setup和teardown的優缺點:

命名方式靈活,不局限於setup和teardown名稱命名
conftest.py 配置里可以實現數據共享,不需要import就能自動找到一些配置
scope="module" 可以實現共享前置條件, 每一個.py文件調用一次
scope="session" 以實現多個.py跨文件使用一個session來完成多個用例(也就是當我們有多個.py文件的用例時候,
如果多個用例只需調用一次fixture,那就可以設置為scope="session",並且寫到conftest.py文件里)

3、Fixture的使用

一般是來裝飾用例執行前的預置條件的,並且一般是將裝飾的這個函數寫進配置文件conftest.py

(這個配置文件通常這樣命名,並且可以存在多個的,但是同一個目錄里面只能一個,記住了:這個配置文件也只針對存放的這個目錄生效!!!)

為什么要這樣使用:

比如在:

同一個.py文件里面,或者不同的.py文件內,一個用例需要登錄,另外的用例不需要登錄,那么登錄方法在這種情況下就是前置條件了,那么這個時候使用setup是辦不到的。

解決方法:利用fixture登錄方法寫入到conftest.py配置文件內,然后其他需要用到的時候直接調用,不需要的就不調用。這就很方便了!

 

conftest.py配置文件  需要注意的是:

conftest.py  腳本名稱是固定的不可修改

conftest.py  和運行的用例要在同一個pakage下,並且那個package下存在有__init__.py文件,不能把它刪除了

不需要import導入 conftest.py,當pytest用例運行時會自動查找

 

 

 

 


4、實際應用:
1、@pytest.fixture()-----------------類似setup
2、@pytest.fixture(scope='module\class\session')---類似setup
3、yield ----------------------------類似teardown

 

4.1、當在相同一個.py文件內,調用相同方法時:(處於同一文件中,直接對要調用的方法,進行使用@pytest.fixture()裝飾器,然后將就可以了。)

新建:test_demo.py
import pytest @pytest.fixture() #@pytest.fixture()里面沒有參數,此時默認scope="function",此時針對函數有效 def login(): #fixture裝飾的函數,是可以有return 返回值的--使用yeild來接收返回值,后面詳細說,如果沒有return默認是None。   print("這是登錄方法") def test_case1(login): #需要登錄后才能執行這個用例,那么直接傳入login方法的名稱即可   print("這是查詢功能") def test_case2(): # 不傳login   print("這是搜索功能")

def test_case3(login):
  print("這是搜索功能") if __name__ == "__main__":    pytest.main(["-v", "test_demo.py"])

------>>執行結果可見:

同一.py文件中,遇到有些功能需要先登錄,有的不需要,那么這個時候就可以使用@pytest.fixture()裝飾登錄函數,將登錄變成前置條件,

當有需要使用登錄的函數方法時,直接將登錄函數名稱傳入,即相當於調用了。(那么執行結果就是先調用登錄函數方法,然后執行其他函數方法)

 

 

 


4.2、當有多個.py文件需要調用相同的前置功能時,那么就可以建一個配置文件conftest.py,

    然后pytest運行用例時會默認讀取conftest.py里面的配置方法

新建配置文件(注意名稱): conftest.py-------->>必須為這個!否則pytest找不到
import pytest
@pytest.fixture()      #不傳參數時默認是@pytest.fixture(scope="function")
def login():
  print("這是登錄功能")

  

新建test_demo1.py:
import pytest
def test_case1(login): #傳入login
  print("用例1")

def test_case2(): # 不傳login
  print("用例2")

if __name__ == "__main__":
  pytest.main(["-v", "test_demo1.py"])
新建test_demo2.py:
import pytest def test_case4(login): #傳入login   print("用例4") def test_case5(): # 不傳login   print("用例5") if __name__ == "__main__":   pytest.main(["-v", "test_demo2.py"])

結果可見:

將login函數寫到了配置文件中,且使用@pytest.fixture裝飾login函數;

然后單獨去運行demo1.py或者demo2.py,都可以實現分別去調用這個寫進了配置文件conftest.py的前置的 登錄方法

 

 

同上面的 例4.1 是@pytest.fixture( ) 不傳參數的操作,

如果傳參數呢?接下來請看:

@pytest.fixture(scope='module')       #module作用是當前整個.py文件都會生效,用例調用時,直接將函數名傳入當做參數來使用並調用,並且只調用一次

例1:新建test_demo.py:(當都調用相同的操作方法時)
import pytest
@pytest.fixture(scope="module")
def open():
  print("打開瀏覽器訪問至百度首頁")

def test_case1(open):
  print("這是查詢")

def test_case2(open):
  print("用這是搜索")

if __name__ == "__main__":
  pytest.main(["-s", "test_demo.py"])

運行結果會看見:2個用例都調用了open,open()方法會在執行用例前 運行一次
例2:新建test_demo.py:   (當一個用例調用,一個用例不調用時)
import pytest
@pytest.fixture(scope="module")
def open():
  print("打開瀏覽器訪問至百度首頁")

def test_case1():  #不引用
  print("用例1")

def test_case2(open):   #case2引用open函數
  print("用例2")

if __name__ == "__main__":
  pytest.main(["-s", "test_demo.py"])

結果open只會在case2之前運行一次。(因為只case2 使用了open函數)

  

 

4.3、yield 實現結束操作(同teardown)

新建test_demo.py:

import pytest
@pytest.fixture(scope="module")
def open():
  print("打開瀏覽器,訪問至百度首頁")

  yield  #建議!!!:編寫用例時,yield一般放前置方法里面,注意yield的位置,是寫在結束操作之前,且所有用例執行完之后才執行一次
  print("這是teardown操作")
  print("關閉瀏覽器")

def test_case1(open):
  print("用例1")

def test_case2(open):
  print("用例2")

if __name__ == "__main__":
  pytest.main(["-v", "test_demo.py"])


結果:因為@pytest.fixture(scope="module"),module是只針對當前.py模塊文件生效的,
    yield一般是放在前置方法里面的(即被@pytest.fixture()裝飾過的函數方法)
    並且用例里面都調用了open()操作,在所有用例執行前執行一次open,然后運行用例,最后所有用例執行完之后,才執行一次yield后面的結束操作 注:yield在用例里面充當了teardown操作。就算用例執行報錯,yield還是會正常執行不會被影響

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM