selenium的WebDriver中常用的元素操作有:
- clear() 清除文本
- send_keys() 模擬按鍵輸入
- click() 單擊元素
而更豐富的鼠標(biāo)操作均被封裝在WebDiver的ActionChains類中,ActionChains類提供的常用方法有:
- context_click() 右擊
- double_click() 雙擊
- drag_and_drop() 拖動(dòng)(比如選中多個(gè)文件)
- move_to_element() 鼠標(biāo)懸停
- perform() 執(zhí)行所有ActionChains中存儲(chǔ)的行為
使用格式:
...
from selenium.webdriver.common.action_chains import ActionChains
...
# 執(zhí)行右鍵點(diǎn)擊的操作
ActionChians(瀏覽器驅(qū)動(dòng)實(shí)例).context_click(元素).perform()
...
# 執(zhí)行雙擊的操作
ActionChains(瀏覽器驅(qū)動(dòng)實(shí)例).double_click(元素).perform()
...
# 執(zhí)行拖動(dòng)操作
ActionChains(瀏覽器驅(qū)動(dòng)實(shí)例).drag_and_drop(源元素,目標(biāo)元素).perform()
...
# 執(zhí)行鼠標(biāo)懸停操作
ActionChains(瀏覽器驅(qū)動(dòng)實(shí)例).move_to_element(元素).perform()
...
# 不寫.perform()就不執(zhí)行操作
蟲師的《selenium 2 自動(dòng)化測(cè)試實(shí)戰(zhàn)》中使用的例子是對(duì)360網(wǎng)盤進(jìn)行操作,而本人不想去注冊(cè)一個(gè)360網(wǎng)盤了,就用百度云盤代替。通過對(duì)書上代碼的修改與完善,腳本能自動(dòng)完成自動(dòng)登錄百度云盤、右鍵點(diǎn)擊云盤首頁(yè)文件夾、懸停查看個(gè)人菜單、雙擊進(jìn)入文件夾、多選文件夾中文件并將其移動(dòng)到當(dāng)前文件夾下的子文件夾、從子文件夾中把某些文件選中右鍵移動(dòng)到其他文件夾等操作,還有×掉登錄后百度網(wǎng)盤推送新功能的小窗口(小聲說一句,bd是真的流氓。一個(gè)新功能推送,右下角明明有不再提醒選項(xiàng),然后點(diǎn)了并沒有卵用 每次進(jìn)去都強(qiáng)迫看一次(╯°Д°)╯︵┻━┻ 煩人)。
源代碼如下:
import time
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
flag = 1
t = 1
driver = webdriver.Firefox()
driver.get("http://pan.baidu.com")
# 前端知識(shí)吧 必須要等待 沒加載出來元素就找不到
time.sleep(2)
# 必須的 百度云盤默認(rèn)二維碼登錄 如果不點(diǎn)擊賬號(hào)密碼登錄 賬號(hào)、密碼的輸入框就都是不可用的
driver.find_element_by_id("TANGRAM__PSP_4__footerULoginBtn").click()
# 賬號(hào)密碼 每次輸入賬號(hào)密碼之前都先清除輸入框中數(shù)據(jù)
driver.find_element_by_id("TANGRAM__PSP_4__userName").clear()
driver.find_element_by_id("TANGRAM__PSP_4__userName").send_keys("用戶名")
driver.find_element_by_id("TANGRAM__PSP_4__password").clear()
driver.find_element_by_id("TANGRAM__PSP_4__password").send_keys("密碼")
# 登錄
driver.find_element_by_id("TANGRAM__PSP_4__submit").click()
# time.sleep(10)
# sleep時(shí)間長(zhǎng)了 就會(huì)出現(xiàn) ConnectionAbortedError: [WinError 10053] 你的主機(jī)中的軟件終止了一個(gè)已建立的連接
# 由于客戶端在發(fā)送請(qǐng)求后,還沒等服務(wù)器響應(yīng)就斷開了連接 后臺(tái)程序處理時(shí)間長(zhǎng)導(dǎo)致連接斷開
# 就像在手機(jī)app里面切換功能過快導(dǎo)致閃退一樣
# 使用while來判斷 每秒定位一次彈出推送小窗口的x
# 定位到就停止循環(huán) 定位不到就通過循環(huán)次數(shù)來控制停止循環(huán)
while flag ==1 and t < 10:
try:
time.sleep(1)
t += 1
driver.find_element_by_xpath("/html/body/div[5]/div[1]/div/span").click()
except:
flag = 1
else:
flag = 0
# 右鍵點(diǎn)擊
right_click1 = driver.find_element_by_link_text("文件夾名")
ActionChains(driver).context_click(right_click1).perform()
time.sleep(2)
# 鼠標(biāo)懸停 查看個(gè)人菜單
above = driver.find_element_by_class_name("user-name")
ActionChains(driver).move_to_element(above).perform()
time.sleep(2)
# 鼠標(biāo)雙擊 百度云盤雙擊和單擊文件夾效果一樣 都是進(jìn)入文件夾
doubleclick = driver.find_element_by_link_text("文件夾名")
ActionChains(driver).double_click(doubleclick).perform()
# 會(huì)刷新頁(yè)面 所以等待1s
time.sleep(1)
# 鼠標(biāo)拖放操作(鼠標(biāo)點(diǎn)擊a,移動(dòng)到b時(shí)松開) 選中多個(gè)文件
source_element = driver.find_element_by_link_text("文件名1")
target_element1 = driver.find_element_by_link_text("文件名2")
ActionChains(driver).drag_and_drop(source_element,target_element1).perform()
# 移動(dòng)多個(gè)文件到某文件夾
target_element2 = driver.find_element_by_link_text("子文件夾名")
ActionChains(driver).drag_and_drop(source_element,target_element2).perform()
# 查看拖放操作的結(jié)果
# 瀏覽器頁(yè)面有刷新時(shí) 就算是同一個(gè)頁(yè)面 同種布局 之前定位的元素也不能用 每個(gè)定位只針對(duì)當(dāng)前頁(yè)面
time.sleep(3) # 百度云盤會(huì)顯示移動(dòng)中 所以需要等待時(shí)間
target_element2 = driver.find_element_by_link_text("子文件夾名")
ActionChains(driver).double_click(target_element2).perform()
# 選中這幾個(gè)文件
time.sleep(2)
source_element = driver.find_element_by_link_text("文件名1")
target_element1 = driver.find_element_by_link_text("文件名2")
ActionChains(driver).drag_and_drop(source_element,target_element1).perform()
# 右鍵點(diǎn)擊選中文件
right_click2 = driver.find_element_by_link_text("文件名1或2")
ActionChains(driver).context_click(right_click2).perform()
# 單擊 移動(dòng)到
time.sleep(1)
driver.find_element_by_xpath("右鍵菜單中的 移動(dòng)到 的xpath").click()
# 會(huì)出現(xiàn)個(gè)小窗口 羅列整個(gè)百度云盤的目錄結(jié)構(gòu)
time.sleep(1)
# 選中目標(biāo)文件夾
driver.find_element_by_xpath("某文件夾的xpath").click()
# 單擊確認(rèn)
driver.find_element_by_xpath("/html/body/div[11]/div[3]/a[2]/span/span").click()
time.sleep(1)
driver.quit()
總結(jié):
1.定位元素需要考慮頁(yè)面加載的問題。
如網(wǎng)速慢、瀏覽器卡,定位元素前就需要多sleep幾秒。即能夠定位到元素的前提是元素已經(jīng)加載完畢,否則哪來的元素地址定位。不注意這條規(guī)則,會(huì)經(jīng)常導(dǎo)致定位不到元素。
通過腳本操作頁(yè)面時(shí),如果某個(gè)操作會(huì)使頁(yè)面重新加載資源,則在新的頁(yè)面上操作之前需要重新定位元素,不管該元素是否在之前的代碼里定位過,也不管加載前后的頁(yè)面是不是表現(xiàn)的一樣。即在腳本里面定位過的元素都只是針對(duì)定位時(shí)的頁(yè)面,不對(duì)之前之后的頁(yè)面產(chǎn)生作用;只要頁(yè)面在某個(gè)操作后重新加載資源,這個(gè)頁(yè)面就不是之前的頁(yè)面了。未重新定位便使用該元素會(huì)報(bào)錯(cuò),錯(cuò)誤信息如下:

2.程序的健壯性還不夠。自動(dòng)化測(cè)試web中,網(wǎng)絡(luò)不好,響應(yīng)時(shí)間過長(zhǎng),各種情況導(dǎo)致的定位不到元素都是經(jīng)常遇到的事情,在腳本里怎么去處理這些突發(fā)狀況就是一個(gè)需要不斷思考、不斷完善的過程了。盡善盡美、全都適用是不可能的,只能針對(duì)每一版應(yīng)用進(jìn)行相應(yīng)的修改。
這也是自動(dòng)化測(cè)試明明應(yīng)該減輕了很多測(cè)試人員的負(fù)擔(dān),但測(cè)試人員還是任務(wù)繁重的原因了,大部分時(shí)間都花在了一開始編寫腳本上和之后根據(jù)項(xiàng)目情況、需求變更維護(hù)腳本上。
3.selenium使用close()和quit()關(guān)閉的區(qū)別:
- close() 關(guān)閉當(dāng)前標(biāo)簽欄
- quit() 退出瀏覽器,關(guān)閉驅(qū)動(dòng),徹底退出WebDriver
4.需要找個(gè)時(shí)間了解一下time模塊中slee(t)方法的工作原理(菜鳥教程中說是推遲調(diào)用線程的運(yùn)行,t表示進(jìn)程掛起的時(shí)間)、selenium中判斷frame的原理以及WebDriver API文檔。
Selenium-Python中文文檔 WebDriver API傳送門