譯者 | 晶顏
審校 | 重樓
摘要:Python是測試自動化的最佳編程語言之一,掌握以下7點(diǎn)技巧與最佳實(shí)踐可以進(jìn)一步提升測試自動化的性能。
如果你曾使用過JavaScript、Node或其他編程語言執(zhí)行自動化測試,便會發(fā)現(xiàn)使用Python進(jìn)行自動化測試要容易得多。Python的易用性、高普及率及其提供的大量庫都使其成為測試自動化的最佳編程語言之一。
本人長期從事Python測試自動化項(xiàng)目工作,積累了一些獲取最佳測試效果的技巧。下文將分享7個技巧和最佳實(shí)踐,借助這些內(nèi)容,你將能夠實(shí)現(xiàn)高效的Python測試自動化。
1.根據(jù)項(xiàng)目規(guī)格選擇合適的測試自動化框架
Python自帶測試自動化框架Unittest,但它最適合小項(xiàng)目。如果你期望使用一個能在小型到大型項(xiàng)目中均適用的測試自動化框架,那么Pytest會是更好的選擇。
Pytest提供了一種結(jié)構(gòu)化且高效的方式來編寫測試用例,以實(shí)現(xiàn)更易于管理和可擴(kuò)展的測試自動化。它還擁有最簡單的語法和最全面的插件生態(tài)系統(tǒng)。例如,你可以使用pytest-xdist進(jìn)行并行測試執(zhí)行。此外,還可以在Pytest上運(yùn)行用Unittest或Nose 2編寫的測試用例。
如果你需要進(jìn)行更多的機(jī)器人過程自動化(RPA)工作,那么機(jī)器人框架將是更好的選擇。該框架的語法主要采用人類語言,使用起來較為簡便。對于Web測試,你還可以將其與其他Python測試框架(如Selenium)集成。
如果你所在的團(tuán)隊(duì)采用行為驅(qū)動開發(fā)(BDD)模式,那么Behave則是最好的框架。在Behave中,編寫非技術(shù)受眾可以理解的測試用例是非常容易的。
總之,建議你選擇一個與團(tuán)隊(duì)使用的技術(shù)棧相匹配的框架,以避免可能出現(xiàn)的溝通障礙。但若你是獨(dú)立開展工作,Pytest則是最通用且最常用的框架。
2.在Selenium中使用WebDriverWait來解決計(jì)時問題
前文提及可將Pytest與Selenium集成以進(jìn)行Web測試。Pytest在功能測試方面表現(xiàn)出色,而Selenium則將Web自動化提升到了全新高度,尤其是其強(qiáng)大的WebDriver庫,具備卓越的瀏覽器自動化能力。
在Selenium上運(yùn)行測試時,由于系統(tǒng)需定位元素,必須設(shè)置一段預(yù)設(shè)的等待時間。一旦預(yù)設(shè)時間(如10秒)結(jié)束,驅(qū)動程序便會退出。然而,隱式等待存在一定問題,因?yàn)椴煌脑厮璧牡却龝r間各不相同。
因此,相較于依賴隱式等待,更建議將WebDriverWait與expected_conditions結(jié)合使用,通過創(chuàng)建某些條件,確保在與元素進(jìn)行交互之前,這些條件已得到滿足。
from selenium import Webdriver
from Selenium.Webdriver.common.by import By
from Selenium.Webdriver.support.ui import WebDriverWait
from Selenium.Webdriver.support import expected_conditions as EC
driver = Webdriver.Chrome()
driver.get("https://example.com")
# Wait for the element to be clickable
wait = WebDriverWait(driver, 10)
element = wait.until(EC.element_to_be_clickable((By.ID, "clickableElementId")))
element.click() # Perform action after the element is ready
driver.quit()
若測試頻繁失敗,并不一定意味著Web應(yīng)用程序存在問題,有可能是應(yīng)用程序的代碼或用戶界面發(fā)生了某些變化。為避免因測試失敗而進(jìn)行過多的調(diào)試工作,務(wù)必使用唯一的ID來準(zhǔn)確識別Web元素。
3.使用Pytest參數(shù)化測試以避免重復(fù)測試函數(shù)
Pytest的參數(shù)化測試特性在節(jié)省時間方面的作用不容小覷。在測試自動化過程中,有時需要使用不同的數(shù)據(jù)集對應(yīng)用程序中的相同功能進(jìn)行測試。此時,你無需重復(fù)編寫測試函數(shù),僅需使用pytest.mark.parametrize,便可使單個測試函數(shù)使用不同的參數(shù)多次運(yùn)行。示例代碼如下:
import pytest
@pytest.mark.parametrize("input, expected", [(2, 4), (3, 9), (4, 16)])
def test_square(input, expected):
assert input ** 2 == expected
如果你想了解是否可以使用Python內(nèi)置的測試自動化框架運(yùn)行參數(shù)化測試,那么在某些條件下,答案是肯定的。Unittest本身不支持參數(shù)化測試,但是你可以為此添加一個模塊。具體方法如下所示:
import unittest
from parameterized import parameterized
class TestMathOperations(unittest.TestCase):
@parameterized.expand([
("square of 2", 2, 4),
("square of 3", 3, 9),
("square of 4", 4, 16),
])
def test_square(self, name, input, expected):
self.assertEqual(input ** 2, expected)
4.通過并行測試加速測試執(zhí)行
測試套件中的API、測試用例、數(shù)據(jù)庫和第三方系統(tǒng)越多,執(zhí)行過程中產(chǎn)生的延遲就會越多,這無疑會拖慢開發(fā)速度。值得慶幸的是,有一種方法可以在不篡改測試套件的情況下解決這個問題。Python允許使用Pytest等框架進(jìn)行并行測試,借助此功能,你可以使用多個CPU并行運(yùn)行多個測試。
下面將展示如何使用Pytest執(zhí)行并行測試:
pip install pytest-xdist
pytest -n 4 # Run tests on 4 CPUs
你還可以增加處理負(fù)載的CPU數(shù)量,但是能夠處理負(fù)載的本地基礎(chǔ)設(shè)施有限。如果你的CPU不足以處理你的測試套件,那么建議使用像Lambda這樣的云平臺來測試應(yīng)用程序在不同瀏覽器和操作系統(tǒng)上的表現(xiàn)。
5.將測試自動化融入CI/CD管道中
請相信,如果處于快節(jié)奏的開發(fā)周期中,手動調(diào)整代碼的工作將接連不斷,每次軟件發(fā)生變更時,都得手動對代碼進(jìn)行調(diào)整,幾乎沒有喘息的機(jī)會。
而將Python測試自動化整合到CI/CD管道中,就能夠在代碼發(fā)生更改時自動執(zhí)行測試。如此一來,便能快速發(fā)現(xiàn)漏洞,并及時發(fā)布改進(jìn)后的應(yīng)用版本供用戶使用。
具體操作是把Python測試自動化集成至CI/CD管道里。在項(xiàng)目中添加 Pytest -cov ,通過Pytest命令自動執(zhí)行測試并標(biāo)記出任何問題。具體步驟如下:
- name: Install dependencies
run: pip install pytest pytest-cov
- name: Run tests
run: pytest --cov=my_project
如果你需要處理更大規(guī)模的測試套件,就需要向諸如Jenkins之類的CI工具添加機(jī)器人框架。對于Unittest而言,coverage功能可使測試集成到類似的管道中,示例如下:
script:
- Python -m coverage run -m unittest discover
- Python -m coverage report
6.獨(dú)立運(yùn)行測試
Python測試自動化可能遇到的一個常見問題是,由于測試之間存在相互依賴關(guān)系而導(dǎo)致測試中斷。簡單來說,就是因?yàn)槟硞€測試依賴于其他測試的數(shù)據(jù)或環(huán)境條件,所以一旦其中一個測試被修改,其他測試就可能會因更改引發(fā)的連鎖反應(yīng)而失敗。為解決這一問題,需要將所有測試進(jìn)行隔離,使每個測試在開始運(yùn)行時都不與其他測試產(chǎn)生關(guān)聯(lián)。這樣一來,在進(jìn)行調(diào)試時,就無需顧慮其對其他測試造成的連鎖影響。
以下展示如何在Pytest中運(yùn)用setup和teardown邏輯來確保測試隔離:
import pytest
@pytest.fixture
def clean_environment():
# Setup: Prepare a clean state
print("Setting up a clean environment.")
yield
# Teardown: Reset environment
print("Cleaning up after the test.")
def test_example(clean_environment):
assert 2 + 2 == 4
需要注意的是,Pytest fixture會確保在每次測試后清理你使用的資源,這使得在測試執(zhí)行完畢后,環(huán)境能夠恢復(fù)到初始狀態(tài)。
7.堅(jiān)持最佳測試自動化實(shí)踐原則
在此著重介紹幾個提高Python測試自動化效率的最佳實(shí)踐方法:
- 在開啟測試自動化工作之前,為測試套件設(shè)定測試指標(biāo)。諸如代碼覆蓋率、執(zhí)行的測試用例數(shù)量、通過或失敗情況以及測試執(zhí)行時間等測試指標(biāo),有助于跟蹤測試過程并確定需要解決的瓶頸問題。
- 團(tuán)隊(duì)中的每位成員在很大程度上都應(yīng)掌握編寫端到端(E2E)測試的方法。如此一來,質(zhì)量便不再是事后才考慮的因素,而是從開發(fā)伊始就融入到整個開發(fā)過程當(dāng)中。
- 避免對第三方依賴進(jìn)行測試,例如那些無法掌控的外部網(wǎng)站或服務(wù)器鏈接。對其進(jìn)行測試可能會降低測試速度,而且可能會存在cookie橫幅或其他導(dǎo)致測試失敗的元素。
- 使用斷言來驗(yàn)證測試結(jié)果是否與預(yù)期結(jié)果匹配。
- 及時更新測試自動化工具,以便在最新的瀏覽器版本上對應(yīng)用進(jìn)行測試,從而在應(yīng)用向公眾發(fā)布之前捕獲潛在漏洞。
結(jié)語
自動化測試工作頗具挑戰(zhàn)性,尤其是在面對一系列看似難以解決的錯誤時。實(shí)踐發(fā)現(xiàn),采用測試金字塔模式時,測試自動化出現(xiàn)的錯誤相對較少。在此模式下,重點(diǎn)關(guān)注單元測試和集成測試,而非端到端測試。運(yùn)用上述所強(qiáng)調(diào)的技巧和實(shí)踐方法,便能夠在CI/CD環(huán)境中高效地運(yùn)行持續(xù)回歸測試,并在代碼部署前及時獲取即時反饋信息。
原文標(biāo)題:7 Best Tips and Practices for Efficient Python Test Automation,作者:Pradeesh Ashokan