同學,你為什麼定位不到元素?

在UI自動化中,一般先要找到需要操作的元素對象,然後進行操作。

定位元素成功與否,決定了你的用例的成敗。所以定位元素很重要。

很多同學在用Selenium,Appium等做自動化的時候,有的時候卻總能碰到這個熟悉的錯誤:

NoSuchElementException)

排查了很久,也找不到原因。一下子就懵了,剛才還好好的,這是怎麼了?

UI 自動化,先天不足的就是不夠穩定。很多因素導致定位不到元素。

可能網速導致還還沒載入完全,你卻已經操作了。

可能頁面渲染慢,資源還沒載入完全,特別是弱網情況下明顯。

可能有廣告等彈出框。

可能你等待時間不夠,目標還沒出現,你卻先下手了。

種種因素,讓你獲取不到元素,從而報錯。

下面我們來分析一下,找不到元素的原因有哪些,並找到解決方案。

1.Frame/Iframe原因定位不到元素:

  這個是最常見的原因,首先要理解下frame的實質,frame中實際上是嵌入了另一個頁面,而webdriver每次只能在一個頁面識別,因此需要先定位到相應的frame,對那個頁面里的元素進行定位。

解決方案:

如果iframe有name或id的話,直接使用switch_to_frame(「name值」)或switch_to_frame(「id值」)。如下:

driver=webdriver.Firefox()driver.get(rhttp://www.126.com/)driver.switch_to_frame(x-URS-iframe) #需先跳轉到iframe框架username=driver.find_element_by_name(email)username.clear()#driver.switch_to.frame() python3#driver.switch_to_frame() python2

操作完frame裡面的元素後,要跳出來,接著操作其它的元素。

driver.switch_to.default_content()

2.Xpath描述錯誤原因:

由於Xpath層級太複雜,容易犯錯。但是該定位方式能夠有效定位絕大部分的元素,建議掌握。

我們定位元素的原則是:越簡單越好。如果有id,name,class,css,link等,這是最簡單不過了的。如果實在不好定位,我們可以用xpath,xpath建議不要用絕對路徑,也不宜過長,一般用模糊匹配就可以了。

如:find_element_by_xpath(「//標籤名[@屬性=』屬性值』]」)

find_element_by_xpath("//*[@id=snake)]")

這個屬性可以是id,name,class等任意一種

也可以通過內容來匹配:

如:

find_element_by_xpath("//*[contains(text(),安蜀黍)]")

也可以通過組合匹配:

如:

find_element_by_xpath("//*[contains(text(),安蜀黍) and @id=『snake]")

建議定位完了以後,用我教的那種辦法,在瀏覽器控制台檢驗一下。

3.頁面還沒有載入出來,就對頁面上的元素進行的操作:

這種情況一般說來,可以設置等待,等待頁面顯示之後再操作,這與人手工操作的原理一樣。

設置一下顯式等待時間。

import timetime.sleep(3)

設置等待時間可以解決這個問題,缺點是需要設置較長的等待時間,案例多了測試就很慢,而且你不太清楚要等待多久,等待時間長了,浪費時間,等待時間短了,沒有作用。

推薦大家用智能等待,在某個時間範圍內,如果出現,就直接執行,如果沒有出現,就拋出timeout異常,如下所示:

from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECdriver = webdriver.Chrome()driver.get("https://www.csdn.net/")try: element= WebDriverWait(driver,10).until(EC.presence_of_element_located((By.CSS_SELECTOR,iv.J_close.layer_close)))finally: driver.quit()

4. 不可見元素定位

有些元素,是需要hover在另外一個元素上,才顯示。是invisiable,disable的,如下拉列表等。所以我們先要將滑鼠移到其父節點上,顯示以後才對其定位。移動滑鼠可以這樣寫:

from selenium import webdriverfrom selenium.webdriver.common.action_chains import ActionChainsdriver = webdriver.Chrome()ActionChains(driver).move_to_element(driver.find_element_by_id(父節點)).perform()element = driver.find_element_by_id("子節點")

5. 廣告頁面

見到廣告頁,不要怕,有些是彈框的,有些是浮動的頁面。基本都是能定位得到的。

比如這種:

driver.get("https://www.csdn.net/")time.sleep(5)driver.find_element_by_css_selector(div.J_close.layer_close).click()

又如這種:

driver.get("https://www.1688.com/")time.sleep(5)driver.find_element_by_css_selector(i.identity-icon.identity-close-icon).click()

都能定位得到,直接操作一下就可以了,也可以寫個公共的方法,來處理這些廣告或者彈框。

6. 彈出框

有的時候,會有彈出框來讓你confirm,你必須去點擊一下,否則頁面失去焦點,導致你無法操作

Alert 彈出框:

driver.switch_to.alert.accept() #okdriver.switch_to.alert.dismiss() #cancel

7. 窗體

有的時候,我們操作的時候,會打開另外的窗體,或者瀏覽器的其它tab頁。

句柄已經切過去了,但是焦點還沒切過去,所以需要switch_to.window(),把焦點頁切過去,才能對當前頁進行操作。

思路是: 獲取所有句柄,返回一個list,而要切的對象都是最後一個,所有可以用[-1]直接切過去。

如:

driver.switch_to.window(driver.window_handles[-1])

在實踐中,可能會遇到各種問題,只有通過不斷積累,才能應付自如。

作者簡介:

Snake, 人稱安蜀黍,專職軟體測試10幾年,測試界的老司機。

更多精彩,請關注微信公眾號:python愛好部落


推薦閱讀:

在寫Python的時候,你最喜歡用哪一款IDE?
黃哥推薦學習Python 10本好書。
Day 4-6, 列印、文件、函數
怎樣寫出Pythonic的代碼
Github上同學總結的機器學習和deeplearning方面的很全的資料

TAG:自動化測試 | Selenium | Python |