同学,你为什么定位不到元素?

发表于:2021-10-19 09:41  作者:Snake   来源:知乎

字体: | 上一篇 | 下一篇 |我要投稿 | 推荐标签: 元素定位 selenium

  在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])
  在实践中,可能会遇到各种问题,只有通过不断积累,才能应付自如。

  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理

评 论

论坛新帖



建议使用IE 6.0以上浏览器,800×600以上分辨率,法律顾问:上海信义律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2021, 沪ICP备05003035号
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪公网安备 31010102002173号

51Testing官方微信

51Testing官方微博

扫一扫 测试知识全知道