柚子快報激活碼778899分享:Pytest學習教程
柚子快報激活碼778899分享:Pytest學習教程
前言
? pytest裝飾器是在使用 pytest 測試框架時用于擴展測試功能的特殊注解或修飾符。使用裝飾器可以為測試函數提供額外的功能或行為。 ? 以下是 pytest 裝飾器的一些常見用法和用途:
裝飾器作用@pytest.fixture用于定義測試用例的前置條件和后置操作??梢詣?chuàng)建可重用的測試環(huán)境或共享資源,并將其注入到測試函數中。通常,fixture 可以返回所需的對象或執(zhí)行特定的設置和清理操作。@pytest.mark.parametrize用于參數化測試函數。通過在裝飾的函數上提供參數列表,可以運行多組具有不同輸入的測試用例。這樣可以輕松地擴展測試范圍并減少重復的測試代碼。@pytest.mark.skip使用這個裝飾器可以跳過不需要運行的測試用例。可以附帶參數來提供跳過測試的原因或條件。@pytest.mark.skipif類似于 @pytest.mark.skip,這個裝飾器可以基于條件來跳過特定的測試用例??梢允褂妙A定義的環(huán)境變量、Python 版本、操作系統(tǒng)等作為條件。@pytest.mark.xfail這個裝飾器標記所裝飾的測試用例為 “expected failure”(預期失敗)。也就是說,預計在某些條件下測試將失敗,如果出現預期的失敗,將被視為測試通過;如果測試用例沒有失敗,則會被標記為測試失敗。@pytest.mark.repeat這個裝飾器用于將測試用例重復運行多次??梢灾付ㄖ貜痛螖祦泶_定運行次數。@pytest.mark.usefixtures使用此裝飾器可以在測試函數中直接使用已定義的 fixture,而無需在函數簽名中顯式聲明。這樣可以簡化測試函數的編寫。@pytest.mark.dependency用于聲明測試用例之間的依賴關系,以確保測試用例按正確的順序執(zhí)行。
一、@pytest.fixture裝飾器
? 常用的參數列表及其簡要說明:
參數說明scope指定fixture的作用域,控制fixture的生命周期??蛇x值包括"function"(默認值,每個測試函數調用一次),“class”(每個測試類調用一次),“module”(每個模塊調用一次),或"session"(整個測試會話過程中調用一次)params為fixture指定不同的參數化值??梢允橇斜?、元組或生成器。autouse控制fixture是否自動應用于測試用例。如果將其設置為True,則fixture將自動應用于所有使用它的測試用例。ids為參數化fixture中的每個參數指定一個名稱或標識符列表,以便在測試報告中更好地識別不同的參數。name為fixture指定一個顯示名稱,用于在測試報告中更好地標識fixture。
import pytest
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
# @pytest.fixture 聲明這是一個夾具
# scope="function" 指定了夾具的作用域為函數級別,也就是每個測試函數都會調用該夾具
# autouse=True 指定夾具為自動使用的,也就是不需要在測試函數中顯式地調用夾具,它會自動應用于每個測試函數
@pytest.fixture(scope="function", autouse=True)
def setup_browser():
"""
設置和關閉瀏覽器的測試夾具
"""
driver = webdriver.Chrome() # 初始化Chrome瀏覽器驅動
driver.get("https://www.baidu.com/") # 打開百度首頁
yield driver # 返回driver對象供測試使用
driver.quit() # 測試結束后關閉瀏覽器
# @pytest.fixture 聲明這是一個夾具
# params=[("csdn"......)] 設置夾具的參數列表,夾具被參數化為兩個元組,每個元組包含兩個值,表示不同的搜索引擎關鍵字和期望結果
# name="search_engine" 給夾具指定一個名字,這樣在測試函數中可以引用該夾具
# ids=["CSDN", "Baidu Knowledge"] 為每個參數設置一個標識符,這些標識符在測試報告中將用于標識參數化的實例
@pytest.fixture(params=[("csdn", "CSDN - 專業(yè)開發(fā)者社區(qū)"), ("百度知識", "百度知道 - 全球領先中文互動問答平臺")],
name="search_engine",
ids=["CSDN", "Baidu Knowledge"])
def parametrize_search_engine(request):
"""
參數化的搜索引擎測試夾具
"""
return request.param # 返回包含關鍵字和期望結果的元組
def test_search_home_page(setup_browser):
"""
測試在百度首頁搜索功能
"""
assert "百度一下" in setup_browser.page_source # 檢查頁面源代碼中是否包含"百度一下"
def test_navigation(setup_browser, search_engine):
"""
測試導航功能,包括輸入關鍵字搜索并選擇第一個結果
"""
driver = setup_browser # 獲取瀏覽器驅動對象
keyword, engine = search_engine # 解包含有關鍵字和期望結果的元組
# 輸入指定關鍵字,例如"csdn"或"百度知識"
driver.find_element(By.CSS_SELECTOR, '#kw').send_keys(keyword)
# 點擊搜索按鈕
driver.find_element(By.CSS_SELECTOR, '[class="bg s_btn"]').click()
time.sleep(5)
# 選擇搜索結果中的第一個鏈接進行點擊
driver.find_element(By.CSS_SELECTOR, '[class="result c-container xpath-log new-pmd"] h3 a').click()
time.sleep(5)
# 切換到最新窗口的句柄
driver.switch_to.window(driver.window_handles[-1])
assert driver.title == engine # 檢查打開的頁面標題是否與期望結果一致
def test_autouse_fixture():
"""
測試autouse=True是否生效
"""
assert 1 == 1
if __name__ == '__main__':
pytest.main(['test_run.py', '-v'])
二、@pytest.mark.parametrize裝飾器
import pytest
# @pytest.mark.parametrize裝飾器定義了一個參數化測試函數,允許我們一次運行多組數據進行測試
# 以下參數列表中的每個數據組都將分別傳遞給被裝飾的測試函數
# 參數化允許我們在不同的輸入值之間進行測試,以確保代碼在各種情況下都能正常工作
@pytest.mark.parametrize("a, b, expected", [
(2, 3, 5), # 測試用例1:當a=2,b=3時,預期的輸出結果應為5
(4, 5, 9), # 測試用例2:當a=4,b=5時,預期的輸出結果應為9
(6, 7, 13) # 測試用例3:當a=6,b=7時,預期的輸出結果應為13
])
def test_addition(a, b, expected):
# 斷言語句用于檢查表達式是否為真,以驗證代碼的正確性,
# 如果表達式為False,則會引發(fā)AssertionError異常。
assert a + b == expected # 檢查a + b是否等于預期的輸出結果
# pytest.main()函數被調用來運行測試
# 運行名為'test_run.py'的測試文件,并通過'-v'參數顯示每個測試用例的執(zhí)行結果
if __name__ == '__main__':
pytest.main(['test_run.py', '-v'])
三、@pytest.mark.skip裝飾器
import pytest
# 該測試用例標記為 `@pytest.mark.skip` 裝飾器,表示該測試尚未實現,應跳過執(zhí)行
# 跳過的原因被指定為 "尚未實現",這通常用于臨時禁用尚未準備好或需要進一步開發(fā)的測試
@pytest.mark.skip(reason="Not implemented yet")
def test_multiply():
assert 3 * 4 == 12
if __name__ == '__main__':
pytest.main(['test_run.py', '-v'])
四、@pytest.mark.skipif裝飾器
import pytest
import platform
# 使用 pytest.mark.skipif 裝飾器為測試用例添加條件跳過的標記
@pytest.mark.skipif(platform.system() == "Windows"
and platform.release() == "10",
reason="跳過 Windows 10 版本的測試用例")
def test_linux_run():
# 僅在 Linux 系統(tǒng)下運行的測試代碼
assert 2 == 2
@pytest.mark.skipif(platform.system() == "Linux",
reason="跳過在 Linux 系統(tǒng)下運行的測試用例")
def test_windows_run():
# 僅在 Windows 系統(tǒng)下運行的測試代碼
assert 2 == 2
if __name__ == '__main__':
pytest.main(['test_run.py', '-v'])
五、@pytest.mark.xfail裝飾器
import pytest
# @pytest.mark.xfail 是Pytest測試框架中的一個裝飾器,用于標記預期測試失敗的測試用例
# 預期失敗的測試用例,因為除以零會引發(fā)異常
@pytest.mark.xfail
def test_division():
assert 1 / 0 == 2
# 預期失敗的測試用例,因為除以零不等于1,并且應該引發(fā) ZeroDivisionError 異常
@pytest.mark.xfail(raises=ZeroDivisionError)
def test_division_zero():
assert 1 / 0 == 1
# 預期失敗的測試用例,已知此加法操作會失敗
@pytest.mark.xfail(reason="This test is known to fail")
def test_addition():
assert 2 + 2 == 5
# 預期失敗的測試用例,這個測試實際上是正確的,但我們使用 xfail 標記將其標記為預期失敗
@pytest.mark.xfail
def test_actually_correct():
assert 1 + 1 == 2
if __name__ == '__main__':
pytest.main(['test_run.py', '-v'])
六、@pytest.mark.repeat裝飾器
# pip install pytest-repeat 安裝擴展插件
import pytest
# @pytest.mark.repeat 是 Pytest 測試框架中的一個裝飾器,用于指定一個測試用例的重復運行次數
# 將該測試用例重復執(zhí)行3次
@pytest.mark.repeat(3)
def test_addition():
result = 2 + 2
assert result == 4
if __name__ == '__main__':
pytest.main(['test_run.py', '-v'])
七、@pytest.mark.usefixtures裝飾器
import pytest
@pytest.fixture
def setup_data():
"""
前置條件 - 準備測試數據
"""
print("前置條件-->準備測試數據")
data = "test data"
yield data
print("后置條件-->清理測試數據")
def test_example(setup_data):
"""
示例測試方法,使用了前置條件 fixture 'setup_data'
"""
data = setup_data
print("執(zhí)行示例測試")
assert data == "test data"
@pytest.mark.usefixtures("setup_data")
def test_method():
"""
方法測試,使用了前置條件 fixture 'setup_data',但不接收它作為參數
"""
print("執(zhí)行方法測試")
assert 1 + 1 == 2
if __name__ == '__main__':
pytest.main(['test_run.py', '-s'])
定義了兩個測試函數test_example和test_method,它們都使用了名為setup_data的 fixture 作為測試的前置條件在test_example中,setup_data fixture 被作為測試函數的參數使用。在函數內部,data變量被賦值為setup_data fixture 返回的值,然后用于測試在test_method中,使用了@pytest.mark.usefixtures裝飾器,并將"setup_data"作為參數傳遞。這樣一來,setup_data fixture 的前置條件將在運行test_method之前自動執(zhí)行。雖然在函數體內沒有顯式接收setup_data作為參數,但仍可以通過setup_data執(zhí)行相關操作。這兩種寫法分別適用于需要測試數據作為輸入和不依賴測試數據作為輸入的情況
八、@pytest.mark.dependency裝飾器
# pip install pytest-dependency 安裝擴展插件
import pytest
@pytest.mark.dependency()
def test_login():
# 登錄測試
assert True
# 指定 test_login 為依賴
@pytest.mark.dependency(depends=["test_login"])
def test_search():
# 搜索測試
assert True
# 指定 test_login 和 test_search 為依賴
@pytest.mark.dependency(depends=["test_login", "test_search"])
def test_checkout():
# 結賬測試
assert True
if __name__ == '__main__':
pytest.main(['test_run.py', '-v'])
test_login 測試函數沒有指定任何依賴關系test_search 測試函數指定了 test_login 作為依賴,因此在運行 test_search 之前,會先運行 test_logintest_checkout 測試函數指定了 test_login 和 test_search 作為依賴,因此在運行test_checkout 之前,會先運行 test_login 和 test_search這樣可以確保測試按正確的順序運行,并且測試之間的依賴關系得到滿足。如果某個測試的依賴失敗,那么依賴它的測試也將被跳過執(zhí)行
九、自定義裝飾器
import pytest
# 定義一個自定義裝飾器,用于對測試用例進行分組
@pytest.mark.group1
def test_addition():
assert (1 + 2) == 3
# 定義第二個分組
@pytest.mark.group1
def test_subtraction():
assert (5 - 3) == 2
# 定義第三個分組
@pytest.mark.group2
def test_multiplication():
assert (2 * 3) == 6
# 定義第四個分組
@pytest.mark.group2
def test_division():
assert (10 / 2) == 5
# 如果當前文件被直接執(zhí)行(而不是被導入為模塊),則執(zhí)行以下代碼
if __name__ == '__main__':
# 運行 Pytest 并指定只運行屬于 'group1' 分組的測試用例
pytest.main(['test_run.py', '-m', 'group1'])
通過使用 @pytest.mark.group1 和 @pytest.mark.group2裝飾器,我們可以將測試用例進行邏輯分組。這樣做的好處是可以只運行特定分組的測試用例,而不是運行所有測試用例在上述代碼中,test_addition() 和 test_subtraction() 被分組為’group1’,test_multiplication() 和 test_division() 被分組為 ‘group2’運行以上示例會有警告信息,這時我們需要把group1 和group2 注冊到 pytest中,在項目目錄中創(chuàng)建一個pytest.ini(如果你尚未創(chuàng)建),并在其中定義自定義標記。下面是在pytest.ini 中注冊group1和group2 標記的示例:
[pytest]
markers =
group1: group1 測試的描述
group2: group2 測試的描述
柚子快報激活碼778899分享:Pytest學習教程
相關鏈接
本文內容根據網絡資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉載請注明,如有侵權,聯系刪除。