目錄
測試前的準備
驅動
安裝驅動管理
selenium庫
使用selenium編寫代碼
自動化測試常用函數
元素的定位
cssSelector
xpath
查找元素
點擊/提交對象
模擬按鍵輸入
清除文本內容
獲取文本信息
獲取當前頁面標題和URL
窗口
切換窗口
窗口設置大小
屏幕截圖
關閉窗口
彈窗
警告彈窗+確認彈窗
提示彈窗
等待
強制等待
隱式等待
顯示等待
瀏覽器導航
文件上傳
瀏覽器參數設置
自動化的測試的目標是:通過自動化測試有效減少人力的消耗的同時也提高了測試的質量和效 率。
測試前的準備
驅動
web系統的測試前提是需要打開瀏覽器,通過訪問web服務器來對服務器界面進行一系列的操作。對于手工測試來說,這一系列的操作都需要測試人員手動的,一步一步的來執行測試。那么對于自動化程序來說,程序如何才能打開瀏覽器并執行我們預期的操作流程呢?
驅動一詞應用廣泛,同學們都不會陌生。車有了驅動才能夠讓車跑起來。
計算機有了驅動程序就可以與設備(耳機,攝像頭,麥克風,鍵盤,顯示器等等設備)進行通信。
程序想要打開web瀏覽器就需要安裝web驅動(即WebDriver),WebDriver 以本地化方式驅動瀏覽器。
安裝驅動管理
若通過安裝驅動的方法來啟動瀏覽器,每次瀏覽器更新后對應的驅動也需要更新,為了解決這個問題,selenium中提供了驅動管理工具webdriver-manager,有了webdriver-manager無需手動安裝瀏覽器驅動,即使瀏覽器更新也不會影響自動化的執行。
pip install webdriver-manager
驅動管理:
webdriver-manager支持的python版本為:3.7~3.11
WebDriver Manager是?個開源的命令行?具,它可以自動下載和安裝適用于不同瀏覽器的
WebDriver。通過使用WebDriver Manager,我們可以確保瀏覽器驅動版本始終與瀏覽器版本保持?致,從而避免因版本不匹配而導致的各種問題。
selenium庫
安裝selenium庫
selenium版本很多,統?使用selenium4.0.0版本
pip install selenium==4.0.0
但是我前面說的都是在本地上部署的,也就是在 ctrl+r --> cmd?中輸入的內容。但是我們寫腳本是在PyCharm中,所以我們還是要把selenium和webdriver-manager安裝到PyCharm中。
最終需要下面2個內容(版本要一樣,這樣后面說的自動化測試常見函數在使用過程中才不會有偏差)
使用selenium編寫代碼
在谷歌瀏覽器中使用自動化的方式來搜索迪麗熱巴
復制方式:選擇器
import timefrom selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from webdriver_manager.chrome import ChromeDriverManager#創建谷歌瀏覽器驅動
ChormIns=ChromeDriverManager().install()
#創建瀏覽器對象來調用驅動
driver=webdriver.Chrome(service=Service(ChormIns))
time.sleep(2)
#輸入 https://www.baidu.com
driver.get("https://www.baidu.com/")
time.sleep(2)
#在百度輸入框中,輸入關鍵詞"迪麗熱巴" #chat-textarea
driver.find_element(By.CSS_SELECTOR,"#chat-textarea").send_keys("迪麗熱巴")
time.sleep(5)
#點擊百度一下按鈕
element=driver.find_elements(By.CSS_SELECTOR,"#chat-submit-button")
element[1].click()time.sleep(2)
#關閉瀏覽器
driver.quit()
圖中的 "#chat-textarea" 是以Copy selector復制下來的元素,?selector表達式屬于選擇器的一種
自動化測試常用函數
元素的定位
web自動化測試的操作核心是能夠找到頁面對應的元素,然后才能對元素進行具體的操作。常見的元素定位?式非常多,如id,classname,tagname,xpath,cssSelector
常用的主要由cssSelector和xpath
cssSelector
選擇器的功能:選中頁面中指定的標簽元素
選擇器的種類分為基礎選擇器和復合選擇器,常見的元素定位方式可以通過id選擇器和子類選擇器來進行定位。
定位百度首頁的“百度熱搜”元素,可以使用通過id選擇器和子類選擇器進行定位:
#s-hotsearch-wrapper > div > a.hot-title > div
“搜索輸入框元素”
#chat-textarea
“百度一下按鈕”:
#chat-submit-button
xpath
XML路徑語言,不僅可以在XML文件中查找信息,還可以在HTML中選取節點。
?xpath使用路徑表達式來選擇xml文檔中的節點
xpath語法中:
獲取HTML頁面所有的節點
//*
獲取HTML頁面指定的節點
//[指定節點]
獲取一個節點中的直接子節點
/
例子://span/input
使用指定索引的方式獲取對應的節點內容
注意:xpath的索引是從1開始的。
便捷的生成selector/xpath的方式:右鍵選擇復制"Copy selector/xpath"
XPath://*[@id="hotsearch-content-wrapper"]/li[5]/a/span[2]
查找元素
find_element
find_element(方式"元素") 這里只能查找一個元素
driver.find_element(By.CSS_SELECTOR,"#chat-textarea").send_keys("迪麗熱巴")
這里方式 --> 選擇器? ?查找元素是搜索框(以Copy selector的方式)
find_elements
find_elements(方式"元素") 這里只能查找多個元素
點擊/提交對象
click()
# 找到百度一下
element=driver.find_elements(By.CSS_SELECTOR,"#chat-submit-button")
# 點擊按鈕
element[1].click()
模擬按鍵輸入
send_keys("")
模擬鍵盤輸入,因此鍵盤上可以輸入的內容都可以填寫上去
# 在百度輸入框中,輸入關鍵詞"迪麗熱巴" #chat-textarea
driver.find_element(By.CSS_SELECTOR,"#chat-textarea").send_keys("迪麗熱巴")
清除文本內容
連續的send_keys會將多次輸入的內容拼接連接在一起,若想重新輸入,需要使用清除方法。
所以輸入文本后又想換一個新的關鍵詞,這里就需要用到 clear()
#在百度輸入框中,輸入關鍵詞"迪麗熱巴" #chat-textarea
driver.find_element(By.CSS_SELECTOR,"#chat-textarea").send_keys("迪麗熱巴")
time.sleep(2)
#首先要先查找到搜索框并清除搜索框中的內容
element=driver.find_elements(By.CSS_SELECTOR,"#chat-textarea")
element[1].clear()
time.sleep(2)
#在在搜索框中輸入關鍵詞古力娜扎
driver.find_element(By.CSS_SELECTOR,"#chat-textarea").send_keys("古力娜扎")
獲取文本信息
如果判斷獲取到的元素對應的?本是否符合預期呢?獲取元素對應的文本并打印一下~~
獲取文本信息: text
text=driver.find_element(By.CSS_SELECTOR,"#hotsearch-content-wrapper > li:nth-child(5) > a > span.title-content-title").text
print(text)
問題:是否可以通過 text 獲取到“百度一下按鈕”上的文字“百度一下”呢?嘗試一下
可以看到,這里并沒有輸出任何內容出來,原因如下
解決方案:get_attribute("屬性名稱")
text=driver.find_element(By.CSS_SELECTOR,"#su").get_attribute("value")
assert text=="百度一下"
print(text)
獲取當前頁面標題和URL
獲取當前頁面標題:title
獲取當前頁面URL:current_url
窗口
打開一個新的頁面之后獲取到的title和URL仍然還是前一個頁面的?
當我們手工測試的時候,我們可以通過眼睛來判斷當前的窗口是什么,但對于程序來說它是不知道當前最新的窗口應該是哪一個。對于程序來說它怎么來識別每一個窗口呢?每個瀏覽器窗口都有?個唯一的屬性句柄(handle)來表示,我們就可以通過句柄來切換
切換窗口
在百度首頁點擊圖片,跳轉界面后,我們打印出跳轉后的標題和URL觀察情況
解決方法如下:
預備知識
獲取當前頁面句柄:driver.current_window_handle
獲取所有頁面句柄:driver.window_handles
print("before:"+driver.title)
print("before:"+driver.current_url)
#查找圖片并點擊
driver.find_element(By.CSS_SELECTOR,"#s-top-left > a:nth-child(6)").click()
#獲取當前頁面的句柄---第一個標簽頁
curWindow = driver.current_window_handle
#獲取所有句柄
allWindows = driver.window_handles
#遍歷所有的句柄,切換到新頁面
for handle in allWindows:if handle!=curWindow:#切換句柄driver.switch_to.window(handle)
print("after:"+driver.title)
print("after:"+driver.current_url)
driver.quit()
窗口設置大小
#窗?最?化
driver.maximize_window()
time.sleep(1)
#窗?最?化
driver.minimize_window()
time.sleep(1)
#窗?全屏
driver.fullscreen_window()
time.sleep(1)
#?動設置窗???
driver.set_window_size(1024,768)
time.sleep(1)
屏幕截圖
我們的自動化腳本一般部署在機器上自動的去運行,如果出現了報錯,我們是不知道的,可以通過抓拍來記錄當時的錯誤場景
driver.save_screenshot('./baidu.png')
由于圖片給定的名稱是固定的,當我們多次運行自動化腳本時,歷史的圖片將被覆蓋
如何將歷史的圖片文件保存下來:每次生成的圖片文件名稱都不一樣(帶時間)
filename="autotest-"+datetime.datetime.now().strftime("%Y-%m-%d-%H%M%S")+'.png'
print(filename)
driver.save_screenshot("./images/"+filename)
關閉窗口
driver.close()
注意:窗口關閉后driver要重新定義
# #查找圖片并點擊
driver.find_element(By.CSS_SELECTOR,"#s-top-left > a:nth-child(6)").click()
# #獲取當前頁面的句柄---第一個標簽頁
curWindow = driver.current_window_handle
# #獲取所有句柄
allWindows = driver.window_handles
# #遍歷所有的句柄,切換到新頁面
for handle in allWindows:if handle!=curWindow:#切換句柄driver.switch_to.window(handle)
print("after:"+driver.title)
print("after:"+driver.current_url)
driver.close()
# 獲取所有窗口句柄
handles = driver.window_handles
# 切換到第一個窗口
driver.switch_to.window(handles[0])
text=driver.find_element(By.CSS_SELECTOR,"#su").get_attribute("value")
assert text=="百度一下"
# 獲取所有窗口句柄
handles = driver.window_handles
# 切換到第一個窗口
driver.switch_to.window(handles[0])類似這種切換窗口才能繼續關閉
彈窗
彈窗是在頁面是找不到任何元素的,這種情況怎么處理?使用selenium提供的Alert接口
警告彈窗+確認彈窗
alert = driver.switchTo.alert //確認
alert.accept() //取消
alert.dismiss()
driver.get("file:///D:/Acode/c-recording-test-course--2024/selenium-html/alert.html#")
time.sleep(2)
#點擊調起彈窗
driver.find_element(By.CSS_SELECTOR,"#tooltip").click()
alert = driver.switch_to.alert
time.sleep(1)
#確認
#alert.accept()
#取消
alert.dismiss()
# 彈窗關閉之后才能執行下面的代碼
driver.find_element(By.CSS_SELECTOR,"#tooltip").click()
time.sleep(1)
提示彈窗
alert = driver.switch_to.alert
alert.send_keys("hello")
alert.accept()
alert.dismiss()
driver.get("file:///D:/Acode/c-recording-test-course--2024/selenium-html/Prompt.html")
time.sleep(2)
#點擊調起彈窗driver.find_element(By.CSS_SELECTOR,"body > input[type=button]").click()
alert = driver.switch_to.alert
time.sleep(1)
#在彈窗中的輸入框中輸入內容
alert.send_keys("測試課")
time.sleep(1)
#確認
alert.accept()
time.sleep(1)
#取消
#alert.dismiss()
注意:彈窗中輸入的內容是看不到的!
等待
通常代碼執行的速度比頁面渲染的速度要快,如果避免因為渲染過慢出現的自動化誤報的問題呢?可以使用selenium中提供的三種等待方法:
強制等待
time.sleep()單位:秒??
調用該方法時,程序會直接阻塞,等待指定秒數后繼續執行后面的代碼
優點:使用簡單,調試的時候比較有效
缺點:影響運行效率,浪費大量的時間
隱式等待
隱式等待是一種智能等待,他可以規定在查找元素時,在指定時間內不斷查找元素。如果找到則代碼繼續執行,直到超時沒找到元素才會報錯。
- 它會在指定的時間范圍內,持續嘗試查找元素。
- 如果在超時前找到了元素,就會立即停止等待,繼續執行后續代碼;
- 只有直到超時都沒找到元素,才會拋出 “元素未找到” 的異常
implicitly_wait() 參數:秒
#隱式等待5秒
driver.implicitly_wait(5)
隱式等待作用域是整個腳本的所有元素。即只要driver對象沒有被釋放掉( driver.quit() ),隱 式等待就一直生效。
優點:智能等待,作用于全局
顯示等待
顯式等待的工作機制就是在預先設定的超時時間范圍之內進行等待,只要滿足操作的條件就會繼續執行后續代碼
WebDriverWait(driver,sec).until(functions)
functions :涉及到selenium.support.ui.ExpectedConditions包下的 ExpectedConditions類
式例:
from selenium.webdriver.support import expected_conditions as EC
#expected_conditions as EC 這里是對expected_conditions起來別名
wait = WebDriverWait(driver,2)
wait.until(EC.invisibility_of_element((By.XPATH,'//*
[@id="2"]/div/div/div[3]/div[1]/div[1]/div')))
WebDriverWait(driver, 2)
第一個參數:指定要綁定的瀏覽器驅動實例,顯式等待會基于此驅動監聽頁面狀態。
第二個參數:設置最長超時時間(單位:秒),表示最多等待多久。這里的2表示最長等待2秒。
#顯示等待
wait=WebDriverWait(driver, 3)wait.until(EC.invisibility_of_element((By.XPATH,'/html/body/input')))
driver.get("file:///D:/Acode/c-recording-test-course--2024/selenium-html/Prompt.html")driver.find_element(By.CSS_SELECTOR,"body > input[type=button]").click()
#等待彈窗是否出現
wait.until(EC.alert_is_present())
#彈窗出現向下執行
alert = driver.switch_to.alert
alert.send_keys("hello")
alert.accept()
優點:顯示等待是智能等待,可以自定義顯示等待的條件,操作靈活
缺點:寫法復雜
隱式等待和顯示等待?起使用效果如何呢?
#隱式等待設置為10s,顯?等待設置為15s,那么結果會是5+10=15s嗎?
driver.implicitly_wait(10)
wait = WebDriverWait(driver,15)
start = time.time()try:res = wait.until(EC.presence_of_element_located((By.XPATH,'//*
[@id="2"]/div/div/div[3]/div[1]/div[1]/div/div/div')))except:end = time.time()print("no such element")
driver.quit()print(end-start)
運行結果:
瀏覽器導航
常見操作:
1)打開網站
?driver.get("https://tool.lu/")
2)瀏覽器的前進、后退、刷新
driver.back()
driver.forward()
driver.refresh()
文件上傳
點擊文件上傳的場景下會彈窗系統窗口,進行文件的選擇。 selenium無法識別非web的控件,上傳文件窗口為系統自帶,無法識別窗口元素 但是可以使用sendkeys來上傳指定路徑的文件,達到的效果是一樣的
driver.get("file:///D:/Acode/c-recording-test-course--2024/selenium-html/upload.html")
#找到選擇文件按鈕后發送要上傳的文件
driver.find_element(By.CSS_SELECTOR,"body > div > div > input[type=file]").send_keys("D:\\1\\1.txt")
time.sleep(3)
這里不需要click的,這個是前端的邏輯,這個地方只需要直接輸入文件就行,點擊之后,是打開彈窗選擇文件
瀏覽器參數設置
無頭模式:程序在后端運行,界面看不到頁面的表現
自動化打開瀏覽器默認情況下為有頭模式
#創建谷歌瀏覽器驅動
ChromIns=ChromeDriverManager().install()
#瀏覽器參數配置
options=webdriver.ChromeOptions()
#添加無頭模式
options.add_argument("--headless")
#創建谷歌瀏覽器驅動對象
driver=webdriver.Chrome(service=Service(ChromIns),options=options)
driver.quit()
運行結果:
頁面加載策略
options.page_load_strategy = '加載方式'
頁面加載發式主要有三種類型:
策略 | 說明 |
normal | 默認值,等待所有資源下載 |
eager | DOM訪問已準備就緒,但諸如圖像的其他資源可能仍在加載 |
none | 完全不會阻塞WebDriver |
#1.打開瀏覽器----驅動管理
ChromeIns=ChromeDriverManager().install()
#瀏覽器參數配置
options = webdriver.ChromeOptions()#添加頁面加載策略
# options.page_load_strategy = 'normal' #等待所有的資源加載完成
options.page_load_strategy = 'eager' #DOM訪問就緒
#options.page_load_strategy = 'none' #完全不阻塞,直接繼續往下執行腳本###創建谷歌瀏覽器驅動對象
driver=webdriver.Chrome(service=Service(ChromeIns),options=options)
driver.get("https://haokan.baidu.com/")
print(driver.title)
driver.quit()