专栏首页软件测试testclassSelenium必须掌握的元素定位方法

Selenium必须掌握的元素定位方法

Web端的UI自动化测试,目前使用比较多的就是Python+Selenium。当前一些UI自动化测试工具也是基于Selenium做开发的。 最近经常有童鞋后台询问selenium元素定位方法,其实网上学习资料很多,只要你肯动手,都可以搜的到。元素定位对于自动化测试来说是比较重要而且繁琐的一件事。接下来就来讲一下如何使用webdriver提供的基本元素定位方法。 再次声明:本站点已经和百度、必应、谷歌等各大搜索引擎达成长期的战略合作协议,你有任何疑问都可以通过以上公司提供的免费服务得到解答。

测试环境

selenium:3.12.0 python:Python 3.6.5 windows:windows10 x86_64 IDE:Visual Studio Code Session info: chrome=68.0.3440.84 Driver-info: chromedriver=2.37.544315,platform=Windows NT 10.0.17134 x86_64)

是否打开了多个窗口

在页面操作过程中有时候点击某个链接会弹出新的窗口,这时就需要主机切换到新打开的窗口上进行操作。例如,百度账户注册,打开的就是两个窗口,从登录窗口点击“注册”打开的新窗口。所以这时候我们需要处理多窗口。

WebDriver提供了switch_to.window()方法,可以实现在不同的窗口之间切换。详细操作代码如下:

#Baidu.py
#www.testclass.cn

#Altumn#2018-11-5
from selenium import webdriverimport timedriver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get("http://www.baidu.com")
# 获得百度搜索窗口句柄
sreach_windows = driver.current_window_handledriver.find_element_by_link_text("登录").click()
driver.find_element_by_link_text("立即注册").click()
# 获得当前所有打开的窗口的句柄

all_handles = driver.window_handles
# 进入注册窗口
for handle in all_handles:    
    if handle != sreach_windows:
       driver.switch_to.window(handle)
       print("Now Register Window!")
       driver.find_element_by_id("TANGRAM__PSP_3__userName").send_keys("Username")
       driver.find_element_by_id("TANGRAM__PSP_3__phone").send_keys("Password")
       time.sleep(5)driver.quit()

是否有表单嵌套

在Web应用中经常会遇到iframe/frame表单嵌套页面的应用,WebDriver只能在一个页面上对元素识别与定位,对于iframe/frame表单内嵌页面上的元素无法直接定位。这时就需要通过switch_to.frame()方法将当前定位的主体切换为iframe/frame表单的内嵌页面中。 单个表单嵌套:

#www.testclass.cn
#Altumn

#2018-11-5

from selenium import webdriverdriver = webdriver.Chrome()
driver.get("https://www.testlcass.cn")driver.switch_to.frame("wpCalendarLayer")
#输入iframe/frame的name属性;
driver.find_element_by_id("id").click()
driver.switch_to.default_content()#跳回最外层的页面;

driver.quit()

多个表单嵌套: 有时候也会遇到多个表单的嵌套,这样我们就需要一层层的跳转,从第一层跳转到要定位元素所在的那层表单。处理完业务如果需要跳转到其他层表单,需要跳转到最外层的页面,然后再逐一跳转表单。

#www.testclass.cn

#Altumn

#2018-11-5

from selenium import webdriverdriver = webdriver.Chrome()
driver.get("https://www.testlcass.cn")driver.switch_to.frame("main")#输入iframe/frame的name属性;跳转第一层表单;

driver.switch_to.frame("wpCalendarLayer")#输入iframe/frame的name属性;跳转第二层表单;

driver.find_element_by_id("id").click()
driver.switch_to.default_content()#跳回最外层的页面;

driver.quit()

iframe/frame没有可用的属性:

switch_to.frame()方法通过表单的id 或name属性进行定位。但是有的时候iframe/frame没有可用的id和name属性值,那么这时候我们可以根据以下方式进行元素定位:

#www.testclass.cn

#Altumn
#2018-11-5
from selenium import webdriverdriver = webdriver.Chrome()
driver.get("https://www.testlcass.cn")
#先通过xpth定位到iframe

main = driver.find_element_by_xpath('//*[@name="main"]')
#再将定位对象传给switch_to.frame()方法
driver.switch_to.frame(main)
……
driver.switch_to.parent_frame()#切换到上一层的frame,对于层层嵌套的frame很有用

元素不可见

在UI自动化测试中,有时候会遇到页面元素无法定位的问题,包括xpath等方法都无法定位,是因为前端元素被设置为不可见导致。通过F12工具查看元素发现元素的display:none方法是设置元素不可见,这就是导致为什么通过定位页面元素无法定位的原因。那么这时候我们可以通过JS方法实现修改元素属性值,进而达到元素实现可见或者不可见的功能。 例如:百度主页功能菜单栏”更多产品”一项,默认属性是可见display:block,我们接下来可以通过JS操作元素属性修改,操作步骤如下:

1.进入百度首页; 2.修改”更多产品”一项的属性值display:block为display:none; 3.修改”更多产品”一项的属性值display:none为display:block; 4.点击”更多产品”; 详细操作代码:

#Baidu.py
#www.testclass.cn

#Altumn#2018-11-5

from selenium import webdriverimport timedriver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get("http://www.baidu.com")
#修改display属性为'none',把"更多产品"功能按钮隐藏;
js = "document.getElementsByName('tj_briicon')[0].style.display='none';"

# 调用js脚本
driver.execute_script(js)
time.sleep(5)
# 修改display属性为'block',把"更多产品"功能按钮显示;

js = "document.getElementsByName('tj_briicon')[0].style.display='block';"
# 调用js脚本

driver.execute_script(js)
#判断元素是否在页面上可见;
element = driver.find_element_by_name("tj_briicon")
print(element.is_displayed)
driver.find_element_by_name("tj_briicon").click()

页面元素不可见的元素虽然在界面上不显示,但是在DOM树中,这些元素webdriver也可以找到。HTML DOM的操作方法有很多,本文在此暂不敖述,以后会出详细使用方法。例如:

document.getElementsByClassName() #返回文档中所有指定类名的元素集合,作为 NodeList 对象。

document.getElementById()         #返回对拥有指定 id 的第一个对象的引用。

document.getElementsByName()      #返回带有指定名称的对象集合。

document.getElementsByTagName()   #返回带有指定标签名的对象集合。

元素不满足条件

有些元素存在但是不可见;或者你的操作步骤缺少前提步骤。例如,百度主页工具栏的”搜索设置”功能。默认就是不可见的,这时我们需要鼠标悬停操作,让设置的下拉内容显示出来。所以,鼠标悬停“设置”链接上就是前提条件。

如果把鼠标从”搜索设置”上面移开,你会发现display属性值为none,它所在的整个

标签就是因为这个属性的变化而隐藏的。如下所示,把鼠标从”搜索设置”上面移开:

如下所示,把鼠标移动到”搜索设置”上面,display属性值为block:

详细鼠标悬停操作代码如下:

#www.testclass.cn
#Altumn
#2018-11-5

from selenium import webdriver
# 引入 ActionChains 类
from selenium.webdriver.common.action_chains import ActionChainsdriver = webdriver.Chrome()
driver.get("https://www.baidu.cn")
# 定位到要悬停的元素
above = driver.find_element_by_link_text("设置")
# 对定位到的元素执行鼠标悬停操作

ActionChains(driver).move_to_element(above).perform()

元素不唯一

元素的定位方法有很多,定位方式需要灵活运用。有时候在定位元素的时候,明明感觉自己的用法没有错,脚本语法也完全没错,可是为什么定位不到呢?无论用什么定位方法,可以先使用find_elements_by_xxx()来定位一组元素。如果统计结果是0,说明你的定位方法找不到任何元素,元素本身不存在。如果大于1,说明你这种定位方法不是唯一的。那么就需要把元素打印出来,查看第几个是你所需要的元素:

详细元素定位代码如下:

#Baidu.py#www.testclass.cn
#Altumn
#2018-11-5
from selenium import webdriverimport timedriver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get("https://www.baidu.com/")
driver.maximize_window()
#定位一组元素;

elements=driver.find_elements_by_name("tj_settingicon")
print(len(elements))
#循环打印出每个元素的属性值;
for i in range(len(elements)):
   print("第" + str(i) + "个元素")
   print(elements[i].get_attribute("name"))
   print(elements[i].get_attribute("class"))

输出结果如下所示:

PS C:\Users\WangXiao\Desktop\mystuff> cd 'C:\Users\WangXiao\Desktop\mystuff'; ${env:PYTHONIOENCODING}='UTF-8'; ${env:PYTHONUNBUFFERED}='1'; & 'C:\Users\WangXiao\AppData\Local\Programs\Python\Python36\python.exe' 'c:\Users\WangXiao\.vscode\extensions\ms-python.python-2018.7.1\pythonFiles\PythonTools\visualstudio_py_launcher.py' 'C:\Users\WangXiao\Desktop\mystuff' '51070' '34806ad9-833a-4524-8cd6-18ca4aa74f14' 'RedirectOutput,RedirectOutput' 'c:\Users\WangXiao\Desktop\mystuff\python2.py'DevTools listening on ws://127.0.0.1:12958/devtools/browser/589110e2-92eb-46e5-924c-1b8fbded0a2f2第0个元素
tj_settingicon
pf
第1个元素
tj_settingicon
pf

你可以通过元素的属性判断你要定位的元素:

driver.find_elements_by_name("tj_settingicon")[0].click()
driver.find_elements_by_name("tj_settingicon")[1].click()

元素动态id属性

有时候,你要定位的元素的属性是动态的,即每次重新打开页面该元素的id或者class等属性是动态生成的。元素定位时会抛出NoSuchElementException的错误。怎么判断元素属性是否是动态?很简单,一般看到元素属性里有拼接一串数字的,就很有可能是动态的。想要分辨,刷新一下浏览器再看该元素,属性值中的数字串改变了,即是动态属性了。在此介绍一个解决方法,使用xpath根据动态元素属性进行定位: xpath中提供了三个非常好的方法来为我们定位部分属性值:

driver.find_element_by_xpath("//input[contains(@id, 'bt-class')]")     
# id属性包含'bt-class',并且固定不变;
driver.find_element_by_xpath("//input[starts-with(@id, 'bt-class')]")  
# id属性开头为'bt-class',并且固定不变;
driver.find_element_by_xpath("//input[ends-with(@id, 'bt-class')]") 
# id属性结尾是'bt-class',并且固定不变;

元素未出现就进行了操作

有时候,在跑脚本的时候,明明单步调试的时候元素可以定位到,并且可以正常操作,但是在跑测试案例的时候,反而报错。这时候就需要考虑是否界面的切换,或者功能的跳转导致元素建在缓慢,所以我们需要加上等待;同样,WebDriver提供了两种类型的等待:显式等待和隐式等待两种方法。 显式等待: 显式等待使WebdDriver等待某个条件成立时继续执行,否则在达到最大时长时抛出超时异常(TimeoutException);

#Baidu.py
#www.testclass.cn
#Altumn
#2018-11-5
from selenium import webdriverfrom selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ECdriver = webdriver.Firefox()
driver.get("http://www.baidu.com")element = WebDriverWait(driver, 5, 0.5).until(EC.presence_of_element_located((By.ID, "kw")))
element.send_keys('selenium')
driver.quit()

WebDriverWait类是由WebDirver 提供的等待方法。在设置时间内,默认每隔一段时间检测一次当前页面元素是否存在,如果超过设置时间检测不到则抛出异常。

WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)
driver :浏览器驱动。
timeout :最长超时时间,默认以秒为单位。
poll_frequency :检测的间隔(步长)时间,默认为0.5S。
ignored_exceptions :超时后的异常信息,默认情况下抛NoSuchElementException异常。

隐式等待: WebDriver提供了implicitly_wait()方法来实现隐式等待,默认设置为0。它的用法相对来说要简单得多。

#Baidu.py#www.testclass.cn#Altumn#2018-11-5from selenium import webdriverfrom selenium.common.exceptions import NoSuchElementExceptionfrom time import ctimedriver = webdriver.Firefox()
# 设置隐式等待为20秒;
driver.implicitly_wait(20)
driver.get("http://www.baidu.com")
#处理异常机制;
try:
   print(ctime())
   driver.find_element_by_id("kw_test").send_keys('selenium')except NoSuchElementException as e:
   print(e)finally:
   print(ctime())
   driver.quit()

强制等待: 设置等待最简单的方法就是强制等待,其实就是time.sleep()方法,不管它什么情况,让程序暂停运行一定时间,时间过后继续运行;缺点时不智能,设置的时间太短,元素还没有加载出来,那照样会报错;设置的时间太长,则会浪费时间.这个方式一般比较少用。

#Baidu.py

#www.testclass.cn
#Altumn

#2018-11-5
from selenium import webdriverimport timedriver = webdriver.Chrome()  
driver.implicitly_wait(20) # 隐性等待,最长等20秒;
 driver.get('https://www.baidu.com')
time.sleep(3)#强制等待3秒;

driver.quit()

本文分享自微信公众号 - 软件测试testclass(testclass_cn),作者:Altumn

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-11-05

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Selenium获取网页源码

    Python+Selenium可以做网络爬虫。所以,我们可以从网页源码中爬出想要的信息。

    Altumn
  • Selenium操作Frame中的页面元素

    在Web应用中经常会遇到网页中嵌套多个Frame框架的情况。这种情况下,如果直接去定位嵌套在Frame页面中的元素就会抛出NoSuchElementExcept...

    Altumn
  • Selenium控制浏览器静默模式运行

    日常的UI自动化测试过程中,可以打开无界面的浏览器实现静默模式完成自动化测试。静默模式只需要使用浏览器的内核,不显示界面。

    Altumn
  • Python3 Selenium+Chr

    以前抓取动态网页是用PhantomJS + Selenium + ChromeDriver,但是新版的Selenium不支持PhantomJS了,程序跑的时候总...

    py3study
  • python appium操作手机及ap

    py3study
  • selenium-webdriver|4 常用API介绍

    <option value="自动化测试">自动化测试</option>

    测试邦
  • selenium切换窗口后定位元素出现问题的解决方案

    在做UI自动化的过程中,有时需要由一个窗口跳转到另一个窗口,这时直接去定位页面元素,可能会出现问题,这时,我们需要将driver与新的窗口进行绑定。

    流柯
  • Selenium和PhantomJS 终极最全使用总结

    1. 加载页面[image.png]PhantomJS 截取的是网页的完整页面,包括下拉进度条的内容

    Python疯子
  • python-selenum3 第三天基

    py3study
  • appium+python自动化56-微信小程序自动化

    最近微信的小程序越来越多了,随之带来的问题是:小程序如何做自动化测试? 本篇以摩拜小程序为例,介绍如何定位小程序里面的元素

    上海-悠悠

扫码关注云+社区

领取腾讯云代金券