當涉及自動化前端測試時,選擇理想的編程語言變得極為重要。Python是一種位居榜首的語言,因其易用性和廣泛的社區支持。
此外,Python自動化測試讓您利用流行的庫和框架(如Selenium、pytest和Robot等)提供的功能。使用Python與Selenium有助於充分利用Selenium強大的瀏覽器自動化功能和Python的簡潔性和可擴展性。總的來說,Python自動化測試被廣泛應用於各地的QA,尤其是與Selenium WebDriver一起使用。
在本博客中,我們將深入探討Python在前端方面的細微之處。本博客的學習將有助於利用Python的能力來自動化簡單和複雜的前端場景。
什麼是Python自動化測試?
正如其名,Python自動化測試是使用Python腳本自動化測試的過程。這是用於自動化手動和重複任務的最受歡迎的編程語言之一。
Python自动化测试的一个简单示例涉及利用pytest框架与Selenium自动化前端测试电子商务平台。您可以验证电子商务网站的注册功能,并使用同一会话浏览网站并将所需商品添加到购物车中。通过此测试的最后,您将验证电子商务网站的注册、登录和购物车功能。
最后,您还可以利用Python来自动化系统管理、自动化电子邮件和数据处理任务。由于Python是自动化测试的先决条件,请参考以下视频,深入了解Python的安装。
为什么选择Python进行自动化测试?
既然我们知道为什么测试人员更喜欢Selenium与Python,让我们看一下选择Python进行自动化测试的一些重要原因:
1. 广泛的库和框架
PyUnit(或unittest)是执行Python单元测试的默认测试框架。虽然PyUnit已经默认提供,但Python还支持其他流行的框架,如pytest、Behave、Robot、Lettuce和Nose2。
所有这些都可以与Selenium和Playwright框架充分配合,用于自动化Web浏览器测试。
2. 超级简单的并行测试执行
在Selenium和Python中进行并行测试可以广泛用于执行跨不同浏览器和平台组合的Web浏览器自动化测试。虽然所有支持Selenium的编程语言都支持并行测试执行,但在Python中使用起来非常简单。
3. 多范式编程语言
Python是一种多范式编程语言。因此,它完全支持面向对象编程和结构化编程。Python中的大多数特性支持函数式编程和面向方面的编程。Python与Selenium一起,还可以用于对网站和Web应用进行功能测试。
4. 动态类型
Python语言使用动态类型和迟绑定(或动态名称解析),在执行期间绑定方法和变量名。这个特性对于Python测试自动化非常方便。
Python还提供了诸如Pyre(Python 3的高性能类型检查器)和Mypy等选项,这些都是流行的静态类型检查器。通过这些检查器,Python让您结合动态和静态类型的强大功能。
5. 网页抓取
使用Python进行网页抓取是从网站中提取有意义和有用信息/数据的过程。它主要用于学术研究、竞争对手分析、内容聚合等。
Python提供了许多库和框架,如BeautifulSoup(bs4)、Selenium、Puppeteer和Pyppeteer,这些都简化了从网站中抓取内容的任务。
6. 强大且无忧的报告
在測試自動化中報告提供了對測試執行細微差異的更大可見性(例如通過/失敗的測試百分比,測試環境,截圖等)。給出正確信息的強大報告以簡明易懂的形式發送給必要的利益相關者(團隊中的人),以便他們了解測試進展情況。
如何執行 Python 自動化測試?
現在我們已經了解了 Python 自動化測試的重要性,讓我們開始運行一些測試。我們的討論將主要圍繞使用 Python 進行前端自動化測試。
在開始測試之前,讓我們設置虛擬環境(venv
),這有助於更好地管理環境和依賴關係。 venv
在提供與基礎環境中安裝的套件隔離方面扮演著重要角色。
在終端機上運行命令 virtualenv venv
和 source venv
/bin
/activate
來創建虛擬環境。所有項目執行所需的依賴項(或 Python 套件),如 pytest
, selenium
等,都在 requirements.txt 文件中。
pytest-selenium
pytest-xdist
selenium>=4.6.0
urllib3==1.26.12
requests
py
依賴項
可以通過在終端機上觸發 pip install -r requirements.txt
來安裝。Selenium v4.6.0(或更高版本)將作為安裝過程的一部分安裝。
為了演示,我們將使用 pytest 和 PyUnit(或 unittest)框架執行簡單的 Selenium Python 測試。如果您對這些框架中的任何一個熟悉,建議您在 Python 中使用 fixtures 和在 Selenium Python 中使用 Page Object Model 來改進測試的維護。Selenium 套件本身並未提供測試工具或框架。因此,我們將使用 Selenium 搭配 pytest 和 PyUnit 來自動化與網頁元素的互動。
測試方案
- 前往 LambdaTest Selenium Playground。
- 在頁面上找到輸入表單提交的鏈接。
- 在頁面上輸入所需信息。
- 提交詳細信息,並斷言信息是否未成功提交。
實施(pytest 框架)
以下是上述測試方案的測試腳本:
import os
import pytest
from os import environ
import time
from selenium.webdriver import ChromeOptions
from selenium.webdriver.support.ui import WebDriverWait
from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import Select
from selenium.webdriver.common.by import By
exec_platform = os.getenv('EXEC_PLATFORM')
time_sleep = 2
########################## Locators #########################
xSubmitForm = "//a[.='Input Form Submit']"
xInpName = "//input[@id='name']"
cInpName = "#name"
xInpEmail = "//form[@id='seleniumform']//input[@name='email']"
xInpPassword = "//input[@name='password']"
cssCompany = "#company"
cWebName = "#websitename"
xInpCountry = "//select[@name='country']"
xInpCity = "//input[@id='inputCity']"
cssAddress1 = "[placeholder='Address 1']"
cssAddress2 = "[placeholder='Address 2']"
cssInpState = "#inputState"
cssInpZip = "#inputZip"
cssInpButton = ".bg-lambda-900"
nameSearchBox = "search"
class TestFormInput:
def setup_method(self):
if exec_platform == 'cloud':
username = environ.get('LT_USERNAME', None)
access_key = environ.get('LT_ACCESS_KEY', None)
ch_options = webdriver.ChromeOptions()
lt_options = {}
lt_options["build"] = "Build: Getting Started with Selenium PyTest"
lt_options["project"] = "Project: Getting Started with Selenium PyTest"
lt_options["name"] = "Test: Getting Started with Selenium PyTest"
lt_options["browserName"] = "Chrome"
lt_options["browserVersion"] = "latest"
lt_options["platformName"] = "macOS Sonoma"
lt_options["geoLocation"] = "US"
lt_options["console"] = "error"
lt_options["w3c"] = True
lt_options["headless"] = False
ch_options.set_capability('LT:Options', lt_options)
gridURL = "https://{}:{}@hub.lambdatest.com/wd/hub".format(username, access_key)
self.driver = webdriver.Remote(
command_executor = gridURL,
options = ch_options
)
elif exec_platform == 'local':
ch_options = ChromeOptions()
self.driver = webdriver.Chrome(options=ch_options)
def test_enter_form_details(self):
resultant_str = "Thanks for contacting us, we will get back to you shortly."
driver = self.driver
driver.get("https://www.lambdatest.com/selenium-playground/")
# Commented once the tests are executed in non-headless mode
driver.maximize_window()
wait = WebDriverWait(driver, 5)
try:
element = driver.find_element(By.XPATH, xSubmitForm)
element.click()
elem_name = driver.find_element(By.XPATH, xInpName)
elem_name.send_keys("Testing")
time.sleep(time_sleep)
elem_email = driver.find_element(By.XPATH, xInpEmail)
elem_email.send_keys("[email protected]")
time.sleep(time_sleep)
elem_pass = driver.find_element(By.XPATH, xInpPassword)
elem_pass.send_keys("password")
time.sleep(time_sleep)
elem_comp = driver.find_element(By.CSS_SELECTOR, cssCompany)
elem_comp.send_keys("LambdaTest")
elem = driver.find_element(By.CSS_SELECTOR, cWebName)
elem.send_keys("https://wwww.lambdatest.com")
country_dropdown = Select(driver.find_element(By.XPATH, xInpCountry))
country_dropdown.select_by_visible_text("United States")
time.sleep(time_sleep)
elem = driver.find_element(By.XPATH, xInpCity)
elem.send_keys("San Jose")
time.sleep(time_sleep)
elem = driver.find_element(By.CSS_SELECTOR, cssAddress1)
elem.send_keys("Googleplex, 1600 Amphitheatre Pkwy")
time.sleep(time_sleep)
elem = driver.find_element(By.CSS_SELECTOR, cssAddress2)
elem.send_keys("Mountain View, CA 94043")
time.sleep(time_sleep)
elem = driver.find_element(By.CSS_SELECTOR, cssInpState)
elem.send_keys("California")
time.sleep(time_sleep)
elem = driver.find_element(By.CSS_SELECTOR, cssInpZip)
elem.send_keys("94088")
time.sleep(time_sleep)
# Click on the Submit button
submit_button = driver.find_element(By.CSS_SELECTOR, cssInpButton)
submit_button.click()
time.sleep(2)
try:
element = wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, ".success-msg"))
)
assert resultant_str in element.text, f"'{resultant_str}' not found in the specified element."
except Exception as e:
if exec_platform == 'cloud':
driver.execute_script("lambda-status=failed")
pytest.fail(f"Text '{resultant_str}' not found: {str(e)}")
time.sleep(2)
except Exception as e:
# Catch other exceptions
print(f"Failed: Input Form Demo, generic exception - {e}")
if exec_platform == 'cloud':
driver.execute_script("lambda-status=failed")
if exec_platform == 'cloud':
driver.execute_script("lambda-status=passed")
print(f"PyTest Demo: Test Passed")
def teardown_method(self):
if (self.driver != None):
# self.driver.close()
self.driver.quit()
if __name__ == "__main__":
pytest.main()
代碼步驟
首先,我們導入實施測試所需的必要模塊。由於我們使用 pytest,因此還將 pytest 模塊導入代碼中。
從 selenium.webdriver.support.ui 模塊導入 WebDriverWait 類,這樣我們可以使用顯式等待,以應對動態定位 WebElements 的情況。expected_conditions 模塊提供了一組在 Selenium 中與顯式等待一起使用的預定義的預期條件。
在執行任何操作之前,由於要定位元素,我們首先要定義所需元素的元素定位器。 ID、Name、XPath、Link Text、Partial Link Text 等是一些廣泛使用的Web定位器,可以幫助您在文檔對象模型(DOM)內查找元素。
您可以使用內置於網頁瀏覽器的檢查工具,或者像 POM Builder 這樣的插件(或附加元件),它可以輕鬆找到 WebElements 的 XPath/CSS 選擇器。
一旦識別出Web定位器,可以通過將定位器與 Selenium Python 的find_element()
或 find_elements()
方法結合來定位相應的WebElement(s)。 find_element()
方法返回單個WebElement,而find_elements()
返回與定位器標準匹配的WebElement列表。
如前所述,setup_method()
是 pytest fixture 的一部分,屬於初始化的一部分。該方法在所述測試類下實施的每個測試函數之前調用。
正在實施的測試可以在本機安裝的 Selenium 上運行,也可以在雲測試提供的線上 Selenium 網格上運行。LambdaTest 是一個AI驅動的測試執行平台,可讓您在不同瀏覽器和操作系統上規模運行Python自動化測試。它帶來許多好處,其中主要包括降低維護成本、成本更低以及加速測試執行。
就实施而言,唯一的变化涉及Selenium WebDriver,即在云网格上运行测试时,Selenium中的远程WebDriver会被实例化。自动化能力生成器有助于为打算在测试中使用的测试组合生成能力。
在Selenium 4中,浏览器选项取代了期望的能力。您可以查看Selenium 3与Selenium 4差异的博客,了解更多关于Selenium 4中哪些内容已被弃用。
环境变量LT_USERNAME
和LT_ACCESS_KEY
可以从您的LambdaTest帐户设置>密码和安全中获取。将这些组合与LambdaTest网格URL一起传递,有助于在云网格上执行测试。在test_enter_form_details()
方法中,我们首先通过调用driver.get()
方法导航到测试URL。
接下来,实例化的浏览器窗口会最大化,因为这被认为是Selenium的最佳实践之一。
接下来,使用Selenium中的XPath定位器和find_element()
方法来定位输入表单提交元素。定位后,调用Selenium中的按钮点击来模拟对先前步骤中找到的按钮元素的点击动作。
由于所有测试步骤都涉及定位元素和执行操作,因此我们只关注一些方法。通过CSS选择器在Selenium中定位公司元素的方法如下所示。在Selenium WebDriver中的send_keys()
可帮助发送文本输入到定位的元素中。
下拉選單在網站上被廣泛使用;因此,使用Selenium自動化與下拉選單的互動成為您測試案例的必要步驟。Select
類別位於selenium.webdriver.support.ui模組中,提供了讓您使用Selenium處理下拉選單的方法。
在這裡,一個名稱為country_dropdown
的Select
類別物件被建立,並將輸入設置為使用XPath定位的下拉選單元素。Select
類別的select_by_visible_text()
方法有助於選擇具有與給定字串匹配的可見文字的項目(例如:美國)。
一旦表單中的所有信息被輸入並點擊提交按鈕,我們會等待直到成功訊息字串(預設:隱藏)在頁面上可見。使用ExpectedCondition(即定位元素存在)的顯式等待將一直執行,直到成功訊息不再在頁面上。
如果結果字串不在頁面上,將引發一個斷言。對於雲端執行,lambda-status
變數會根據執行狀態標記為passed/failed。
teardown_method()
夾具包含在類別中的測試執行後清理資源或狀態的實現。if __name__ == "__main__":
構造確保當腳本直接運行時才執行程式碼。pytest.main()
調用pytest框架,進一步發現並執行腳本中所有已啟用(即未標記為skipped)的測試。
測試執行(pytest框架)
將EXEC_PLATFORM
設置為cloud後,在終端上調用以下命令運行LambdaTest雲端網格上的pytest測試:
pytest --verbose --capture=no tests/pytest/pytest_selenium_demo.py
以下是LambdaTest Web自動化儀表板的截圖,顯示測試執行成功:
實現(PyUnit框架)
上述測試方案的測試腳本使用PyUnit框架位於tests/pyunit/pyunit_selenium_demo.py。
從pytest遷移到PyUnit(或unittest)框架時,測試的核心邏輯保持不變。代替pytest
模塊,將unittest
模塊導入代碼中。測試用例類從unittest.TestCase
繼承,通知unittest模塊這是一個測試用例。
pytest fixtures setup_method()
/teardown()
類似於PyUnit框架的setUp()
/tearDown()
方法。 setUp()
和tearDown()
方法包含初始化和去初始化的實現,分別負責初始化和去初始化。
以下是執行測試套件的樣板代碼:
if __name__ == "__main__":
unittest.main()
測試執行(PyUnit框架)
將EXEC_PLATFORM
設置為cloud後,在終端機上調用以下命令來在雲端網格上運行PyUnit測試:
python tests/pyunit/pyunit_selenium_demo.py
下面是LambdaTest Web Automation儀表板截圖,顯示測試執行成功:
如果要在本地安裝的Selenium上運行上述測試,只需將EXEC_PLATFORM
設置為local,然後您就可以進行本地執行了。
頂級Python測試框架
由於Python支持多個測試自動化框架,為您的項目選擇合適的框架變得至關重要。選擇實際上為有效測試奠定了基礎。除了框架的功能外,您還需考慮對所述框架的內部專業知識。以下是一些最佳的Python測試框架:
PyUnit(unittest)
它是Python中提供的默認框架。正如其名稱所示,它主要用於單元測試。PyUnit受Java的JUnit框架啟發,具有類似的結構和功能。
unittest框架還支持測試自動化共享設置和關閉代碼,使測試與報告框架獨立,等等。它還支持以面向對象的方式進行測試套件和測試用例。它還有一個測試運行器,負責協調測試的執行。
pytest
它是Python中最流行的測試自動化框架之一。它使用更簡潔和用戶友好的語法來實現測試。pytest可用於實施單元測試以及測試網站和Web應用程序的復雜功能測試。
使用pytest編寫的測試更加緊湊,因為該框架不需要樣板代碼。pytest具有內置功能,有助於自動發現測試模組和函數。
Robot
它是一個關鍵字驅動的開源Python框架,主要用於機器人流程自動化(RPA)和測試自動化。與pytest框架類似,Robot也是可擴展的。使用人類可讀的語法/關鍵字可以減少學習Robot的曲線。
使用Robot編寫的測試以.robot
擴展名保存。如果打算使用Robot進行前端測試,可以使用SeleniumLibrary,這是Robot框架的Web測試庫。該庫支持豐富的關鍵字(Click Button、Click Image、Open Browser、Drag and Drop等)。
Nose2
它是Nose的後繼者,是一個Python測試框架,擴展了PyUnit(或unittest)框架的功能。如果您之前有unittest的工作經驗,那麼開始使用Nose2相對輕鬆。
Nose2相對於PyUnit的主要優勢在於擁有大量內建的Nose插件,這些插件使測試更加簡便快速。Nose2中的插件有助於測試參數化、更好地組織測試、支持固定測試環境、測試發現等功能。
Behave
這是一個用於行為驅動開發(BDD)的Python框架。測試基於Gherkin語法,該語法基於Given-When-Then格式。
由於測試是在場景和特性文件中實現的,即使非技術人員也可以參與QA流程。SpecFlow(C#)和Cucumber(Java、JS、Ruby)是其他流行的BDD框架。
結論
到目前為止,Python無疑是最適合測試自動化的腳本語言。開始使用Python自動化測試相對容易。它廣泛的測試框架可用於單元測試、跨瀏覽器測試等。請在下方告訴我們您偏好的Selenium測試編程語言以及您如何對比Python,這個無可爭議的自動化測試之王。祝測試愉快!
Source:
https://dzone.com/articles/python-automation-testing-with-examples