準備好WebDriver后,讓我們編寫第一個Web測試!測試將是一個簡單的DuckDuckGo搜索。DuckDuckGo是一個不跟蹤用戶數(shù)據(jù)的搜索引擎。就像任何其他搜索引擎一樣,用戶可以輸入搜索短語并獲得指向匹配網站的鏈接。
在編寫自動化代碼之前,最好總是以簡單的語言編寫測試過程。編寫程序迫使我們首先考慮被測行為。這是我們的測試過程:
導航到DuckDuckGo主頁
輸入搜索詞組
驗證:
結果顯示在結果頁面上
搜索詞出現(xiàn)在搜索欄中
至少一個搜索結果包含搜索短語
這是相當基本的,但涵蓋了端到端的典型搜索行為。
將以下測試功能添加到:tests/test_web.py
def test_basic_duckduckgo_search(browser):
URL = 'https://www.duckduckgo.com'
PHRASE = 'panda'
browser.get(URL)
search_input = browser.find_element_by_id('search_form_input_homepage')
search_input.send_keys(PHRASE + Keys.RETURN)
link_divs = browser.find_elements_by_css_selector('#links > div')
assert len(link_divs) > 0
xpath = f"http://div[@id='links']//*[contains(text(), '{PHRASE}')]"
results = browser.find_elements_by_xpath(xpath)
assert len(results) > 0
search_input = browser.find_element_by_id('search_form_input')
assert search_input.get_attribute('value') == PHRASE
該test_basic_duckduckgo_search
函數(shù)按照Arrange-Act-Assert模式執(zhí)行我們的測試過程。請注意,測試函數(shù)聲明了一個名為的參數(shù)browser
,該參數(shù) 與我們用于ChromeDriver設置和清除的固定裝置相同。每次運行此測試時,pytest都會自動調用固定裝置并注入WebDriver參考。然后,測試函數(shù)使用該browser
變量進行多個WebDriver調用。讓我們看看這些調用是如何工作的。
URL = 'https://www.duckduckgo.com'
該測試將DuckDuckGo主頁的URL聲明為變量,以提高可讀性和可維護性。
PHRASE = 'panda'
這是測試將使用的搜索短語。由于測試涵蓋了“基本”搜索,因此該短語并不太重要。其他行使不同行為的測試應使用更復雜的短語。再次,測試將其聲明在測試功能的頂部,以提高可讀性和可維護性。
browser.get(URL)
測試的起點是DuckDuckGo主頁。此調用將瀏覽器導航到給定的URL。被警告,雖然:此調用并 不會等待頁面加載。它只是啟動加載交互。
search_input = browser.find_element_by_id('search_form_input_homepage')
自動化Web交互的第一步是找到目標元素。元素可能會或可能不會出現(xiàn)在頁面上。自動化必須使用 定位器 來查找元素(如果存在),然后構造一個代表該元素的對象。定位符的類型很多:ID,類名,CSS選擇器,XPaths等。定位器將在頁面上找到所有匹配的元素-可能不止一個。嘗試使用最簡單的定位器,該定位器將唯一地標識目標元素。
要編寫定位器,您需要查看頁面的HTML結構。Chrome DevTools可輕松檢查任何實時頁面的標記。只需右鍵單擊頁面,然后選擇“檢查”。您可以在“元素”選項卡上查看所有元素。對于我們的測試,我們想在DuckDuckGo主頁上找到搜索輸入字段。該元素的 id 屬性值為“ search_form_input_homepage”,如下所示:
我們可以使用WebDriver的find_element_by_id
方法獲取該元素。為search_input
變量分配了代表頁面上搜索輸入元素的對象。請記住,由于WebDriver實例具有隱式等待,因此最多等待10秒鐘,搜索輸入元素才會出現(xiàn)在頁面上。
search_input.send_keys(PHRASE + Keys.RETURN)
有了元素,我們就可以觸發(fā)與它的交互。該send_keys
方法將一系列擊鍵發(fā)送到搜索輸入元素,就像人類用戶會在鍵盤上鍵入一樣。上面的呼叫發(fā)送搜索詞組。最后的RETURN鍵提交搜索。
link_divs = browser.find_elements_by_css_selector('#links > div')
結果頁面應顯示一個div
ID為“ links”的div
元素,每個結果鏈接都有一個子元素。上面的CSS選擇器可以找到所有這樣的結果鏈接div。請注意,“元素”是復數(shù)–此調用將返回一個列表。
assert len(link_divs) > 0
測試必須驗證搜索詞是否確實出現(xiàn)了結果。此assert
語句確保在頁面上至少找到一個結果鏈接。
xpath = f"http://div[@id='links']//*[contains(text(), '{PHRASE}')]"
驗證是否出現(xiàn)了一些結果很好,但是我們還應該驗證結果是否與我們的搜索詞匹配。我們可以使用XPath來精確定位包含文本中搜索短語的結果鏈接。XPath比名稱和CSS選擇器復雜,但它們也更強大。上面的XPath搜索div
ID為“ links”的鏈接,然后查找包含搜索短語文本的后代。
phrase_results = browser.find_elements_by_xpath(xpath)
此調用使用先前串聯(lián)的XPath查找所有元素。我們可以將這兩行合并為一,但是將這些行拆分起來更具可讀性和Python風格。
assert len(phrase_results) > 0
像先前的斷言一樣,此斷言確保至少找到一個元素。這是一個簡單的健全性檢查。它可以變得更強大-就像驗證頁面上的每個結果都包含搜索詞組文本一樣-但這很難。并非每個結果都可以包含搜索短語的確切文本。例如,某些可能具有大寫字符。對于高級驗證,定位器和邏輯將需要更加復雜。由于這是 基本的搜索測試,因此簡單的斷言就足夠了。
search_input = browser.find_element_by_id('search_form_input')
最終斷言驗證搜索短語仍出現(xiàn)在搜索輸入中。上面的行與Arrange階段中的find元素調用相同 。它將再次找到搜索輸入元素。我們?yōu)槭裁床荒?/span>search_input
再次使用該對象?不幸的是,先前的元素已經 過時了。頁面從搜索頁面更改為結果頁面。即使元素看起來相同,也有所不同,并且還需要一個新的定位器。因此,我們需要重新獲取它。
assert search_input.get_attribute('value') == PHRASE
鍵入輸入元素的文本可作為其“值”屬性訪問。該行斷言“值”屬性等于搜索詞組。它驗證該短語沒有消失。
現(xiàn)在,其完整代碼應如下所示(為清晰起見,附加了注釋):tests/test_web.py
"""
This module contains web test cases for the tutorial.
Tests use Selenium WebDriver with Chrome and ChromeDriver.
The fixtures set up and clean up the ChromeDriver instance.
"""
import pytest
from selenium.webdriver import Chrome
from selenium.webdriver.common.keys import Keys
def browser():
# Initialize ChromeDriver
driver = Chrome()
# Wait implicitly for elements to be ready before attempting interactions
driver.implicitly_wait(10)
# Return the driver object at the end of setup
yield driver
# For cleanup, quit the driver
driver.quit()
def test_basic_duckduckgo_search(browser):
# Set up some test case data
URL = 'https://www.duckduckgo.com'
PHRASE = 'panda'
# Navigate to the DuckDuckGo home page
browser.get(URL)
# Find the search input element
# In the DOM, it has an 'id' attribute of 'search_form_input_homepage'
search_input = browser.find_element_by_id('search_form_input_homepage')
# Send a search phrase to the input and hit the RETURN key
search_input.send_keys(PHRASE + Keys.RETURN)
# Verify that results appear on the results page
link_divs = browser.find_elements_by_css_selector('#links > div')
assert len(link_divs) > 0
# Verify that at least one search result contains the search phrase
xpath = f"http://div[@id='links']//*[contains(text(), '{PHRASE}')]"
phrase_results = browser.find_elements_by_xpath(xpath)
assert len(phrase_results) > 0
# Verify that the search phrase is the same
search_input = browser.find_element_by_id('search_form_input')
assert search_input.get_attribute('value') == PHRASE
現(xiàn)在,運行測試以確保它可以運行:
$ pipenv run python -m pytest
============================= test session starts ==============================
platform darwin -- Python 3.7.3, pytest-4.5.0, py-1.8.0, pluggy-0.12.0
rootdir: /Users/andylpk247/Programming/automation-panda/python-webui-testing
collected 9 items
tests/test_math.py ........ [ 88%]
tests/test_web.py . [100%]
=========================== 9 passed in 6.10 seconds ===========================
網絡測試運行時,它將打開Google Chrome。您可以觀看它自動輸入搜索短語,等待結果頁面,然后退出瀏覽器。整齊!
如果測試無法運行,請檢查以下內容:
測試計算機是否已安裝Chrome?
ChromeDriver是否在系統(tǒng)路徑上?
ChromeDriver版本與Chrome版本匹配嗎?
是否有文件系統(tǒng)權限問題?
防火墻是否阻止了任何端口?
測試代碼正確嗎?
聯(lián)系客服