天天看點

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

  在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(r'http://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 time
  time.sleep(3)      

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

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

from selenium import webdriver
  from selenium.webdriver.common.by import By
  from selenium.webdriver.support.ui import WebDriverWait
  from selenium.webdriver.support import expected_conditions as EC
  driver = 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 webdriver
  from selenium.webdriver.common.action_chains import ActionChains
  driver = 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()    #ok
  driver.switch_to.alert.dismiss() #cancel      

  7. 窗體

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

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

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

  如:

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