天天看點

Pytest架構之 - fixture

上篇講了預處理方法setup和teardown可以實作在執行用例前或結束後加入一些操作, 但這種都是針對整個腳本全局生效的, 如果隻是幾個特定的用例需要,

Pytest

fixture

修飾器時用來标記固定的工廠函數,在其他函數、子產品、類或整個工程調用它時會被激活并優先執行,通常會被用于完成預置處理和重複操作

fixture優勢

. 命名方式靈活,不局限于setup和teardown這幾個命名
. conftest.py 配置裡可以實作資料共享,不需要import就能自動找到fixture
. scope="function"    可以實作多個testCase共享前後置
. scope="class"       可以實作多個class共享前後置
. scope="module"      可以實作多個.py共享前後置
. scope="package"     可以實作多個package共享前後置
. scope="session"     可以實作整個session共享前後置
. 參數化的實作
           

fixture參數

@pytest.fixture(scope="function", params=None, autouse=False, ids=None, name=None)

scope:被标記方法的作用域 預設function
    "function": 預設參數,作用于每個測試方法,每個test都運作一次 
    "class": 作用于整個類,每個class的所有test隻運作一次 
    "module": 作用于整個子產品,每個module的所有test隻運作一次 
    "package": 作用于整個package,每個package隻運作一次
    "session": 作用于整個session,每個session隻運作一次 
autouse: 是否自動運作,預設為False不運作(需要引用才執行),設定為True作用域内自動運作
params: list類型,提供參數資料(參數化),供調用标記方法的函數使用 
ids: 參數是配合fixture的params參數用的,如果沒有設定params參數,那麼ids毫無意義;ids參數是給每一項params參數設定自定義名稱用的;params參數值包含的清單有多少項值,那麼ids參數就必須對應有多少項值
name: 裝飾器的名稱,同一子產品的fixture互相調用建議寫個不同的name
           

引用

#!/usr/bin/python3
# coding=utf-8
# Author: 文
###########################   @pytest.fixture()在測試類裡面,通過參數引用   ###########################
import pytest

class Test_One():
    @pytest.fixture()
    def default(self):
        print("-------> default")

    def test_1(self, default_01):    # 函數名直接作為參數引用使用 作用域:隻在該方法前執行
        print("-------> test_1")

    def test_2(self):
        print("-------> test_2")

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

#############    @pytest.fixture()在測試類之外,通過裝飾器@pytest.mark.usefixtures引用    #############
import pytest

@pytest.fixture()
def default():
    print("-------> default")

@pytest.mark.usefixtures("default")  # 作用域:裝飾類則該類中所有方法全部執行,裝飾方法則隻執行該方法
class Test_Two():
    def test_01(self):
        print("------> test_01")

    def test_02(self):
        print("------> test_02")

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

參數scope與作用域

scope = function     =>    setup_class之後每個setup之前執行

scope = class           =>    setup_class之後第一個setup之前執行

scope = module      =>     整個.py子產品檔案第一個setup_class之前執行

scope = package     =>     整個package第一個執行

scope = session       =>     整個session第一個執行

#!/usr/bin/python3
# coding=utf-8
# Author: 文

import pytest

@pytest.fixture(scope="function")
def default_01():
    print("-------> default_01")

@pytest.fixture(scope="class")
def default_02():
    print("-------> default_02")

@pytest.fixture(scope="module")
def default_03():
    print("-------> default_03")

@pytest.fixture(scope="session")
def default_04():
    print("-------> default_04")

@pytest.mark.usefixtures("default_01", "default_02", "default_03", "default_04")
class Test_Two():
    def setup(self):
        print("-------> setup")

    def setup_class(self):
        print("-------> setup_class")

    def test_01(self):
        print("------> test_01")

    def test_02(self):
        print("------> test_02")

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

參數autouse

autouse預設為False不運作(需要手動引用才執行),設定為True作用域内自動運作

#!/usr/bin/python3
# coding=utf-8
# Author: 文

import pytest

class Test_Three():
    @pytest.fixture(autouse=True)   # autouse=True自動執行
    def autouse_01(self):
        print("-------> 自動執行")

    @pytest.fixture(autouse=False)  # autouse=False手動引用才執行
    def autouse_02(self):
        print("-------> 引用執行")

    def test_001(self, autouse_02):
        print("------> test_001")

    def test_002(self):
        print("------> test_002")

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

參數params(參數化)與ids

參數params參數化, ids為給每一項params參數設定自定義名稱(可為空)

#!/usr/bin/python3
# coding=utf-8
# Author: 文

import pytest

@pytest.fixture(params=['a', 'b', 'c'], ids=["ids_1", "ids_2", "ids_3"])
def parameterization(request):      # 傳入參數request 系統封裝參數
    return request.param            # 取清單中單個值,預設的取值方式

class Test_Four():
    def test_0001(self, parameterization):  # 獲得傳回值 request.param
        print("------> test_001")
        print(parameterization)

    def test_0002(self):
        print("------> test_002")

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

執行結果如下:

============================= test session starts =============================
platform win32 -- Python ., pytest-., py-., pluggy-.
rootdir: E:\xxx, configfile: pytest.ini, testpaths: ./testCase
collected  items

testCase/test_two.py::Test_Four::test_0001[ids1] ------> test_001
a
PASSED
testCase/test_two.py::Test_Four::test_0001[ids2] ------> test_001
b
PASSED
testCase/test_two.py::Test_Four::test_0001[ids3] ------> test_001
c
PASSED
testCase/test_two.py::Test_Four::test_0002 ------> test_002
PASSED

==============================  passed in s ==============================
           

參數name

name參數是給fixtrue設定名稱

#!/usr/bin/python3
# coding=utf-8
# Author: 文

import pytest

class Test_Five():
    @pytest.fixture(name='name_01')        # name參數給fixture設定名稱
    def name(self):
        print('------> name')

    def test_01(self, name_01):            # 使用name參數名來引用 -> name_01
        print("------> test_01")

if __name__=='__main__':
    pytest.main(["-s", "test_two.py::Test_Five::test_01"])
           

關鍵字yield

@pytest.fixture()

中,關鍵字

yield

之前的代碼為用例的前置處理方法  關鍵字

yield

之後的代碼為用例的後置處理方法

#!/usr/bin/python3
# coding=utf-8
# Author: 文

import pytest

class Test_Three():
    @pytest.fixture()
    def autouse(self):
        print("-------> yield之前的代碼為用例的前置處理")
        yield
        print("-------> yield之後的代碼為用例的後置處理")

    def test_01(self, autouse):
        print("------> test_01")

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

執行結果如下:

F:\Python3.\python.exe E:/xxx/test_two.py
============================= test session starts =============================
platform win32 -- Python ., pytest-., py-., pluggy-.
rootdir: E:\xxx, configfile: pytest.ini
plugins: html-., metadata-.
collected  item
test_two.py -------> yield之前的代碼為用例的前置處理
------> test_01
.-------> yield之後的代碼為用例的後置處理
==============================  passed in s ==============================
Process finished with exit code 
           
Pytest架構之 - fixture

 ~ 不積跬步無以至千裡

繼續閱讀