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

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

5、addfinalizer關鍵字

yield是當用例執行完之後,會執行yield後面的程式碼,但用例不能有return返回值。

addfinalizer實現功能跟yield一樣,但是用例可以return引數,傳給後面用例。

示例1:

import pytest


@pytest.fixture()
def login(request): # request是Pytest中的一個關鍵字,固定寫法。
    # 步驟1:正常編寫前置用例
    print("開啟APP")
    print("輸入賬號,密碼,進行登入")
    username = '小明'

    # 步驟3:定義用例執行後要執行的程式碼,封裝到一個函式中
    def closeApp():	# 這個closeApp函式命是自定義的
        print("關閉APP")
        
    # 步驟4:執行上面封裝的程式碼。
    # 通過request關鍵字,結束上面的函式。
    request.addfinalizer(closeApp)# 終結函式
	
    # 步驟2:返回引數給測試用例。
    # 返回引數可以是變數,物件,表示式,常量值。
    return username


def test_add_cart(login):  # 步驟3
    print("新增購物車--需要登入")
    # 這裡需要注意: 如果要使用fixture方法返回的資料,
    # 就直接填寫fixture方法名稱。
    # 返回引數的名稱和可以和fixture方法的名稱相同。
    print(f"登陸者:{login}") 


def test_add_address(login):  # 步驟3
    print("新增收貨地址--需要登入")
    print(f"登陸者:{login}")

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

"""
執行結果:

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

test_01.py::test_add_address 開啟APP
輸入賬號,密碼,進行登入
新增收貨地址--需要登入
登陸者:小明
PASSED關閉APP
"""

示例2:

# 示例一個selenium自動化關閉開啟關閉瀏覽器的操作。
import time
import pytest
from selenium import webdriver


@pytest.fixture()
def driver(request):  # request是Pytest中的一個關鍵字,固定寫法。
    # 步驟1:建立瀏覽器驅動物件
    driver = webdriver.Firefox()

    # 步驟3:定義用例執行後要執行的程式碼,封裝到一個函式中
    def end():  # 這個end函式命是自定義的
        driver.quit()

    # 步驟4:執行上面封裝的程式碼。
    # 通過request關鍵字,結束上面的函式。
    request.addfinalizer(end)  # 終結函式

    # 步驟2:返回瀏覽器驅動物件,給測試用例
    # 返回引數可以是變數,物件,表示式,常量值。
    # 返回引數的名稱和可以和fixture方法的名稱相同。
    return driver


def test_baidu(driver):
    """開啟百度"""
    driver.get("http://www.baidu.com")
    time.sleep(3)


def test_163(driver):
    """開啟網易"""
    driver.get("http://www.163.com")
    time.sleep(3)


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

示例3:

使用yield也可以返回資料。(這種方式好神奇)

import pytest


@pytest.fixture()
def login(request):
    print("開啟APP")
    print("輸入賬號,密碼,進行登入")
    username = '小明'
    yield username
    print("關閉APP")


def test_add_cart(login):  # 步驟3
    print("新增購物車--需要登入")
    print(f"登陸者:{login}")


def test_add_address(login):  # 步驟3
    print("新增收貨地址--需要登入")
    print(f"登陸者:{login}")


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

"""
執行結果:
test_01.py::test_add_cart 開啟APP
輸入賬號,密碼,進行登入
新增購物車--需要登入
登陸者:小明
PASSED關閉APP

test_01.py::test_add_address 開啟APP
輸入賬號,密碼,進行登入
新增收貨地址--需要登入
登陸者:小明
PASSED關閉APP
"""

總結:returnyield都表示返回的意思,但是return的後面不能有程式碼,yield的後面可以接程式碼。

6、帶返回值的Fixture

上面例子是帶返回值並且還要實現teardown()後置函式的Fixture寫法。

這裡就是單純的說明帶返回值的Fixture。

我們可以選擇讓Fixture返回我們需要的東西,如果Fixture需要配置一些資料,讀個檔案,或者連線一個資料庫,那麼你可以讓Fixture返回這些資料或資源。

示例:

"""
1.學習目標
    掌握帶返回值的fixture
2.操作步驟
    2.1 編寫帶返回值fixture
    2.2 使用測試用例呼叫
3.需求
"""
import pytest


# 編寫fixture
@pytest.fixture()
def data():
    print("準備好的測試資料")
    return 3 # 返回資料


def test_data(data):
    print("執行用例步驟")
    print(f"得到引數{data}")  # 可以使用在用例步驟中
    assert data == 3  # 使用在斷言中

"""
執行結果:

test_01.py::test_data 準備好的測試資料
執行用例步驟
得到引數3
PASSED
"""

說明:Fixture裝飾類中,也可以實現資料的準備。

7、Fixture實現引數化

Fixture修飾的函式可以通過新增params引數來實現引數化。(實際工作中,不常用此方式)

(1)params引數的使用

request代表Fixture的呼叫狀態,request.param作為返回值供測試使用。

示例:

"""
1.學習目標
    掌握帶引數化fixture編寫
2.操作步驟
    @pytest.fixture(params=[列表格式資料])
    request是pytest中內建關鍵字

"""
import pytest

# 編寫fixture,帶引數
data = [666, 888, 1000]

# request會接收到params=data的引數
# 然後request.param(固定寫法)每次傳遞一個引數
@pytest.fixture(params=data)
def need_data(request):
    return request.param


def test_data(need_data):
    print(f"測試資料:{need_data}")
    assert 666 == need_data

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

"""
test_01.py::test_data[666] 測試資料:666
PASSED
test_01.py::test_data[888] 測試資料:888
FAILED
test_01.py::test_data[1000] 測試資料:1000
FAILED
"""

說明:上面的例子,通過assert簡單判斷下拿到的request.param值,有沒有在原來的引數列表中。實際上就相當於遍歷了一遍引數列表,們可以看到測試方法被呼叫了3次。

(2)進階使用

引數是一個元組列表格式的資料。

"""
1.學習目標
    掌握帶引數化fixture編寫
2.操作步驟
    @pytest.fixture(params=[列表格式資料])
    request是pytest中內建關鍵字
3.需求
4.總結
    1.pytest fixture 主要是用來完成測試用例執行前後操作
        例如:測試前後對資料庫連線/斷開;開啟/關閉瀏覽器APP
    2.fixture還可以用來準備測試資料
        帶引數fixture
        有返回值fixture  (在實際工作中返回資料比較靈活,推薦使用)
    3.fixture中的引數
        scope: 確定fixture作用範圍 預設function,class,module,session
        autouse:當值true時,相當於setup
        name: 對fixture重新命名
"""
import pytest


# 編寫fixture,帶引數
@pytest.fixture(params=[("孫悟空", 666), ("豬八戒", 777), ("沙和尚", 888)])
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()

"""
執行結果:

測試人物:孫悟空
測試分數:666
PASSED測試人物:豬八戒
測試分數:777
PASSED測試人物:沙和尚
測試分數:888
PASSED
"""

總結:params引數支援的格式。

  • 列表[]
  • 元組()
  • 元素列表[(),(),()]
  • 字典列表[{},{},{}],提示:只能取{}整體。
  • 字典元祖({},{},{}),提示:只能取{}整體。

8、@pytest.mark.usefixtures()的使用

@pytest.mark.usefixtures("fixturename")裝飾類也是一種呼叫Fixture的方式。

@pytest.mark.usefixtures("fixturename")裝飾類可以裝飾模組、類、函式、方法。

usefixtures與傳fixture區別:

如果Fixture有返回值,則不能用@pytest.mark.usefixtures("fixturename")裝飾器修飾用例。

如果Fixture沒有返回值,用@pytest.mark.usefixtures("fixturename")裝飾器和@pytest.fixture()裝飾器作用一樣。

示例:

import pytest


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

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


# 方式二:就是把fixture方法傳入usefixtures裝飾器中
@pytest.mark.usefixtures("login")
def test_add_address():  #
    print("新增收貨地址--需要登入")


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

"""
執行結果:

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

test_01.py::test_add_address 開啟APP
輸入賬號,密碼,進行登入
新增收貨地址--需要登入
PASSED關閉APP
"""

相關文章