『德不孤』Pytest框架 — 13、Pytest中Fixture裝飾器(三)

繁華似錦Fighting發表於2022-03-13

9、ids引數說明

ids引數就是給每一個變數起一個別名。

示例:

import pytest

data = [("孫悟空", 666), ("豬八戒", 777), ("沙和尚", 888)]


# ids引數的個數要與params引數的個數相同,用的很少
@pytest.fixture(params=data, ids=['suk', 'zbj', 'shs'])
def need_data(request):
    return request.param


def test_data(need_data):
    print(f"測試人物:{need_data[0]}")
    print(f"測試分數:{need_data[1]}")


if __name__ == '__main__':
    pytest.main()

"""
之前的測試結果:
test_01.py::test_data[need_data0] 測試人物:孫悟空
測試分數:666
PASSED
test_01.py::test_data[need_data1] 測試人物:豬八戒
測試分數:777
PASSED
test_01.py::test_data[need_data2] 測試人物:沙和尚
測試分數:888
PASSED

加上ids引數後的執行結果:只是[]的內容變化了,這就是ids引數的作用
test_01.py::test_data[suk] 測試人物:孫悟空
測試分數:666
PASSED
test_01.py::test_data[zbj] 測試人物:豬八戒
測試分數:777
PASSED
test_01.py::test_data[shs] 測試人物:沙和尚
測試分數:888
PASSED
"""

10、name引數說明

name引數就是給Fixture修飾的方法起個別名。

示例:

import pytest

data = [("孫悟空", 666), ("豬八戒", 777), ("沙和尚", 888)]


# ids引數的個數要與params引數的個數相同,用的很少
@pytest.fixture(params=data, name="abc")
def need_data(request):
    return request.param

# 注意,如果定義了name屬性,用例的方法引數就需要傳入name屬性定義的值。
# 否則將會報錯。
# 還有用例中呼叫引數的使用,也需要使用name定義的別名。
# 即:當取了別名之後,那麼原來的方法名就用不了了。
def test_data(abc):
    print(f"測試人物:{abc[0]}")
    print(f"測試分數:{abc[1]}")


if __name__ == '__main__':
    pytest.main()

"""
執行結果:

test_01.py::test_data[abc0] 測試人物:孫悟空
測試分數:666
PASSED
test_01.py::test_data[abc1] 測試人物:豬八戒
測試分數:777
PASSED
test_01.py::test_data[abc2] 測試人物:沙和尚
測試分數:888
PASSED
"""

11、scope引數說明

scope引數有四個級別:function(預設)classmodulesession

作用範圍:session > module > class > function

  • scope="function"@pytest.fixture()裝飾器如果不寫引數,預設引數就是scope="function"。它的作用範圍是,在每個測試用例執行的前(後)執行一次。
  • scope="class"@pytest.fixture()裝飾器為class級別的時候,Fixture方法只在此class裡所有用例開始執行前(後)執行一次。與class中的function沒有關係。
  • scope="module"@pytest.fixture()裝飾器為module級別的時候,在一個.py指令碼中所有用例開始執行前(後)執行一次。
  • scope="session"@pytest.fixture()裝飾器為session級別的時候,是可以跨.py模組呼叫的,每個.py檔案就是module

(1)scope="function"

import pytest


@pytest.fixture(scope="function")
def login():
    print("開啟APP")
    print("輸入賬號,密碼,進行登入")
    yield  # 當用例執行完成後,執行yield後的程式碼
    print("關閉APP")


def test_add_cart(login):
    print("新增購物車--需要登入")


def test_browser_goods():
    print("瀏覽商品--不需要登入")


if __name__ == '__main__':
    pytest.main()


"""
執行結果: 只作用域方法或者函式範圍

test_01.py::test_add_cart 開啟APP
輸入賬號,密碼,進行登入
新增購物車--需要登入
PASSED關閉APP

test_01.py::test_browser_goods 瀏覽商品--不需要登入
PASSED
"""

(2)scope="class"

import pytest


@pytest.fixture(scope="class")
def login():
    print("\nscope=class 作用域的前置函式\n")
    yield  # 當用例執行完成後,執行yield後的程式碼
    print("\n\nscope=class 作用域的後置函式")


class Test_Demo:

    def test_add_cart(self, login):
        print("新增購物車--測試用例")

    def test_add_address(self):
        print("新增收貨地址--測試用例")


if __name__ == '__main__':
    pytest.main()

"""
執行結果: 只在測試類開始前後執行了

scope=class 作用域的前置函式

新增購物車--測試用例
PASSED
test_01.py::Test_Demo::test_add_address 新增收貨地址--測試用例
PASSED

scope=class 作用域的後置函式
"""

(3)scope="module"

import pytest


@pytest.fixture(scope="module")
def login():
    print("\nscope=module 作用域的前置函式\n")
    yield  # 當用例執行完成後,執行yield後的程式碼
    print("\n\nscope=module 作用域的後置函式")

# 如果該用例不傳入fixture方法,該用例會優先與fixture前置執行
def test_browser_goods(login):
    print("瀏覽商品--不需要登入")

class Test_Demo:

    def test_add_cart(self, login):
        print("新增購物車--測試用例")

    def test_add_address(self):
        print("新增收貨地址--測試用例")

class Test_Demo2:

    def test_add_cart(self, login):
        print("第2次-新增購物車--測試用例")

    def test_add_address(self):
        print("第2次-新增收貨地址--測試用例")


if __name__ == '__main__':
    pytest.main()

"""
執行結果:
說明一下:scope=module時,整個.py模組中fixture只執行一次

scope=module 作用域的前置函式

瀏覽商品--不需要登入
PASSED
test_01.py::Test_Demo::test_add_cart 新增購物車--測試用例
PASSED
test_01.py::Test_Demo::test_add_address 新增收貨地址--測試用例
PASSED
test_01.py::Test_Demo2::test_add_cart 第2次-新增購物車--測試用例
PASSED
test_01.py::Test_Demo2::test_add_address 第2次-新增收貨地址--測試用例
PASSED

scope=module 作用域的後置函式

"""

(4)scope="session"

test_01.py檔案中的用例。

import pytest

@pytest.fixture(scope="session")
def login():
    print("\nscope=session 作用域的前置函式\n")
    yield  # 當用例執行完成後,執行yield後的程式碼
    print("\n\nscope=session 作用域的後置函式")

# 如果該用例不傳入fixture方法,該用例會優先與fixture前置執行
def test_browser_goods(login):
    print("瀏覽商品--不需要登入")

class Test_Demo:

    def test_add_cart(self, login):
        print("新增購物車--測試用例")

    def test_add_address(self):
        print("新增收貨地址--測試用例")


if __name__ == '__main__':
    pytest.main()

test_02.py檔案中的用例。

# 如果該用例不傳入fixture方法,該用例會優先與fixture前置執行
def test_browser_goods():
    print("第2次-瀏覽商品--不需要登入")

class Test_Demo2:

    def test_add_cart(self):
        print("第2次-新增購物車--測試用例")

    def test_add_address(self):
        print("第2次-新增收貨地址--測試用例")

all.py檔案內容:

import pytest

if __name__ == '__main__':
    pytest.main()

"""
執行結果:只在該包內執行一次fixture前後置

scope=session 作用域的前置函式

瀏覽商品--不需要登入
PASSED
test_01.py::Test_Demo::test_add_cart 新增購物車--測試用例
PASSED
test_01.py::Test_Demo::test_add_address 新增收貨地址--測試用例
PASSED
test_02.py::test_browser_goods 第2次-瀏覽商品--不需要登入
PASSED
test_02.py::Test_Demo2::test_add_cart 第2次-新增購物車--測試用例
PASSED
test_02.py::Test_Demo2::test_add_address 第2次-新增收貨地址--測試用例
PASSED

scope=session 作用域的後置函式
"""

說明:

我把session作用域的Fixture寫在了test_01.py檔案中,其實應該提取出來寫到conftest.py檔案中。(後面文章會說明)

all.py檔案就是為了執行所有測試用例,pytest.ini檔案中配置的模糊匹配查詢,這樣兩個檔案中的用例就都能執行到了。

這裡就是一個練習,寫的十分不規範,理解其意思就可以。

12、autouse引數說明

示例:實全部用例的前後置

很簡單,只需要把Fixture中的autouse引數設定為True即可。

Fixture裝飾器會自動執行作用域範圍內的所有用例的前後置。

import pytest

@pytest.fixture(autouse=True)
def login():
    print("輸入賬號,密碼,進行登入")

def test_add_cart():  # 不需要傳入fixture方法
    print("新增購物車--需要登入")

def test_add_address():  # 不需要傳入fixture方法
    print("新增收貨地址--需要登入")


if __name__ == '__main__':
    pytest.main()

"""
執行結果:

輸入賬號,密碼,進行登入
新增購物車--需要登入
PASSED輸入賬號,密碼,進行登入
新增收貨地址--需要登入
PASSED
"""

相關文章