selenium元素定位陷阱规避
为什么selenium可以在各个浏览器上运行?因为selenium在与各个浏览器驱动执行前,会先把脚本转化成webdriver, webdriver wire协议(一种json格式的协议),这样就与脚本无关,其实都变成了同一个协议与浏览器driver执行。由此,selenium在UI自动化中占有举足轻重的地位。那么我们就有必要就其中最基础的UI定位做一些探讨和学习了。
一、selenium的简介
Selenium是基于Web的自动化测试技术,我们操作的对象是web页面。能够用来测试应用程序在不同的浏览器和系统上面是否能够正常的浏览和运行。
二、元素定位的方法
WebDriver属于Selenium体系中设计出来操作浏览器的一套API,它支持多种编程语言,Selenium WebDriver只是Java的一个第三方框架和Spring web开发框架属于同一性质,只是Spring只是在Java语言中存在,其他语言也有用于web开发框架,但不叫Spring。而Selenium WebDriver框架针对不同语言分别开发了该框架,所以,在不同的编程语言里他都叫Selenium WebDriver。
WebDriver提供了八种元素定位方法:
1.id定位
HTML规定id属性在HTML文档中必须是唯一的,示例:FindElement(By.id("kw")));
2.name定位
HTML 规定 name 来指定元素的名称,示例:findElement(By.name("wd"));
3.class定位
HTML规定class来指定元素的类名,示例:findElement(By.className("name head2 j-tag"));
4.tag定位
HTML 的本质就是通过 tag 来定义实现不同的功能,每一个元素本质上也是一个 tag。因为一个 tag 往往用来定义一类功能,所以通过 tag 识别某个元素的概率很低。
5.link 定位
link 定位与前面介绍的几种定位方法有所不同,它专门用来定位文本链接。百度输入框上面的几个文本链接的代码如下:<a class="mnav" name="tj_trnews" href="http://news.baidu.com">新闻</a>
link定位:findElement(By.linkText("新闻"))
6.partial link 定位
parial link 定位是对 link 定位的一种补充,有些文本链接会比较长,这个时候我们可以取文本链接的一部分定位,只要这一部分信息可以唯一地标识这个链接。如:
<a class="mnav" name="tj_lang" href="#">一个很长很长的文本链接</a>,使用
partial link 定位如下:
findElement(By.partialLinkText("一个很长的"))
findElement(By.partialLinkText("文本链接"))
findElement(By.partialLinkText())方法通过元素标签对之间的部分文本信息来定位元素
7.Xpath定位
XPath 是一种在 XML 文档中定位元素的语言。因为 HTML 可以看作 XML 的一种实现,所以 Selenium 用户可以使用这种强大的语言在 Web 应用中定位元素。Xpath定位元素方法有很多种,常用的如下:
1)绝对路径定位
最简单直接的办法就是通过HTML,写出元素的绝对路径,如:findElement(By.xpath("/html/body/nav/div[1]/div[1]/span/a[1]"))
2)利用元素属性定位
除了使用绝对路径外,XPath 也可以使用元素的属性值来定位。如:findElement(By.xpath("//*[@id=\"srch\"]"))
3)层级与属性结合
如果一个元素本身并没有可以唯一标识这个元素的属性值,那么我们可以找其上一级元素,如果它的上一级元素有可以唯一标识属性的值,也可以拿来使用如:findElement(By.xpath("//div[@class='lyct lyct-1']/div/div[2]/ul/li[2]/a"))
4)使用逻辑运算符
如果一个属性不能唯一地区分一个元素,我们还可以使用逻辑运算符连接多个属性来查找元素如:findElement(By.xpath("//input[@id='kw' and @class='su']/span/input"))
8.css 定位
CSS(Cascading Style Sheets)是一种语言,它被用来描述 HTML 和 XML 文档的表现。CSS 使用选择器来为页面元素绑定属性。这些选择器可以被 Selenium 用作另外的定位策略。CSS 可以较为灵活地选择控件的任意属性,一般情况下定位速度要比 XPath 快。
表1 CSS选择器常见语法
选择器 |
例子 |
描述 |
.class |
.intro |
class 选择器,选择class="intro"的所有元素 |
#id |
#firstname |
id 选择器,选择id="firstname"的所有元素 |
* |
* |
选择所有元素 |
element |
p |
元素所有<p>元素 |
element > element |
div > input |
选择父元素为<div>的所有<input> 元素 |
element + element |
div + input |
选择同一级中紧接在<div> 元素之后的所有<input> 元素 |
[attribute=value] |
[target=_blank] |
选择target="_blank" 的所有元素。 |
定位方式 |
Xpath |
CSS |
标签 |
//div |
div |
By id |
//div[@id='eleid'] |
div#eleid |
By class |
//div[@class='eleclass'] |
div.eleid |
By 属性 |
//div[@title='Move mouse here'] |
div[title=Move mouse here] div[title^=Move] div[title$=here] div[title*=mouse] |
定位子元素 |
//div[@id='eleid']/* //div/h1 |
div#eleid>* div >h1 |
三、selenium元素定位陷阱规避
1.动态id定位不到元素
直接填写在浏览器开发者模式中通过copy xpath方式是定位不到,如下:
解决方案一: 通过绝对路径,通过前端元素结构一级一级的数下来如下:
解决方案二:相对路径来解决。可以通过找到唯一的值class,以其为参照来找到对应的元素
2. IFrame原因定位不到元素
IFrame是html中的内联框架,文档中的内嵌html文档
解决方案:切换到IFrame,方法:driver.switchTo.frame(),参数用IFrame元素的id或者name,不支持xpath,或者用IFrame这个元素的WebElement类型。
3.元素定位表达式错误
解决放案:先验证表达式,再写进脚本
/ |
从根节点选取。 |
// |
代表从文档的任意位置开始查找 |
* |
代表任意的元素 |
[] |
代表限制条件 |
@ |
选取属性。 |
手写xpath的方法:
1)在chrome的开发者工具中,ctrl+f,逐步的验证xpath正确性,直到找到想要的元素。
2)在console控制台中,输入$x(“xpath表达式”),验证xpath的正确性,注意:找到唯一的一个元素,才是web自动化定位的最终目标,不管写任何元素的 定位之前,先用$x验证一下表达式的正确性。
4.页面加载未完成
解决方案:增加等待时间,方法:thread.sleep(毫秒时间);
5.浏览器窗口切换
解决方案:通过句柄切换,句柄:windows管理一个任务的特殊标志。
四、云音乐定位的实例
学习中主要用网易云音乐网页版进行了定位测试,实现百度中搜索网易云音乐-登录-QQ登录-点击QQ头像授权登录-成功以后搜索框搜索happy的歌曲。
核心代码如下:
public class MusicTest { public static void main(String[] args){ //设置浏览器存放的路径
System.setProperty("webdriver.chrome.driver",
"D:\\seleniumtests\\chromedriver_win32\\chromedriver.exe"); ChromeOptions options = new ChromeOptions(); //设置chrome浏览器的参数,使其不弹框提示(chrome正在受自动测试软件的控制)
options.addArguments("disable-infobars"); //定义驱动对象为ChromeDriver对象,运行指定的浏览器
WebDriver driver = new ChromeDriver(options); //浏览器窗口最大化,设置一个点
Point p = new Point(1300,20);
//设置浏览器大小
Dimension d = new Dimension(1600,1000); //操作浏览器设置
driver.manage().window().setPosition(p);
driver.manage().window().setSize(d); //访问百度
driver.get("https://www.baidu.com/"); //百度网易云音乐
driver.findElement(By.xpath("//*[@id=\"kw\"]")).sendKeys("网易云音乐");
//提交搜索
driver.findElement(By.xpath("//*[@id=\"kw\"]")).submit(); //等待5s
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} //点击网易云音乐的链接
driver.findElement(By.xpath("//*[@id=\"1\"]/h3/a[1]/em")).click(); //切换窗口,集合set:里面都是字符串
Set<String> handles = driver.getWindowHandles(); //新建一个目标句柄,用于找到想要的句柄之后存放
String targetHandleCM = null; //循环查找所有句柄
for(String handle : handles){ //获取切换后句柄的浏览器标题是网易云音乐
if(driver.switchTo().window(handle).getTitle().equals("网易云音乐")){ //将这个找到的句柄作为目标句柄
targetHandleCM = handle;
}
} //点击网易云音乐的登录,动态id不好定位
// driver.findElement(By.xpath("//*[@id=\"auto-id-N4GvXnq8c42v6OmS\"]/a")).click(); //方案一:点击登录,绝对路径
//driver.findElement(By.xpath("/html/body/div[1]/div[1]/div[1]/div[1]/a")).click(); //方案二:点击登录,相对路径,找到一个唯一值class,以其为参照找到登录元素
driver.findElement(By.xpath("//div[@class=\"m-tophead f-pr j-tflag\"]/a")).click(); //点击qq登录 ,动态id,此处以class为参照找qq登录元素
//driver.findElement(By.xpath("//*[@id="auto-id-he1mw81UnDRge7Ui"]/div/div[2]/ul/li[2]/a")).click(); //找不到该元素
driver.findElement(By.xpath("//div[@class='lyct lyct-1']/div/div[2]/ul/li[2]/a")).click(); //切换窗口,集合set:里面都是字符串
Set<String> handles2 = driver.getWindowHandles(); //新建一个目标句柄,用于找到想要的句柄之后存放
String targetHandleQQ = null; //循环查找所有句柄
for(String handle2 : handles2){ //获取切换后句柄的浏览器标题是网易云音乐
if(driver.switchTo().window(handle2).getTitle().equals("QQ帐号安全登录")){ //将这个找到的句柄作为目标句柄
targetHandleQQ = handle2;
}
}
//切换到目标窗口QQ帐号安全登录
driver.switchTo().window(targetHandleQQ); //等待
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} //切换iframe
driver.switchTo().frame("ptlogin_iframe"); //第二种方法:用iframe这个元素的 Webelement类型
// WebElement iframe = driver.findElement(By.xpath("//iframe[@id='ptlogin_iframe']"));
// driver.switchTo().frame(iframe); //点击头像完成登录
driver.findElement(By.xpath("//*[@id=\"img_out_1062807640\"]")).click(); //切换回来网易云音乐
driver.switchTo().window(targetHandleCM); //等待
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} //搜索框输入happy
driver.findElement(By.xpath("//*[@id=\"srch\"]")).sendKeys("happy"); } }
五、小结
本文主要讲述了一下UI定位的常用方法,以及经常会遇到的坑。面对如今前端框架经常调整,常常没有固定的id或者唯一的name,我们很难维护脚本的稳定性。只有不断的拓展自己的知识面,掌握更多的定位方法,灵活选择和巧妙的结合使用,才能避免少犯错误。进而提高UI自动化的可使用性。
后期可以将Java selenium+Maven+TestNG+Jenkins框架结合起来,运用套件的形式将不同的单个UI case串联起来执行。通过git持续集成在Jenkins上面,运用TestNG会在执行后默认生成报告或者Jenkins上面的图形插件,进而可以更直观的看到自动化用例的执行结果。
selenium元素定位陷阱规避的更多相关文章
- 自动化测试基础篇--Selenium元素定位
摘自https://www.cnblogs.com/sanzangTst/p/7457111.html 一.Selenium元素定位的重要性: Web自动化测试的操作:获取UI页面的元素,对元素进行操 ...
- Selenium3 + Python3自动化测试系列二——selenium元素定位
一.selenium元素定位 Selenium对网页的控制是基于各种前端元素的,在使用过程中,对于元素的定位是基础,只有准去抓取到对应元素 才能进行后续的自动化控制,我在这里将对selenium8种元 ...
- selenium元素定位之css选择器
在selenium元素定位时会用到css选择器选取元素,虽说xpath在定位元素时能解决大部分问题,但使用css选择器选取元素也是一种不错的选择. css相较与xpath选择元素优点如下: 表达式更加 ...
- selenium元素定位篇
Selenium webdriver是完全模拟用户在对浏览器进行操作,所有用户都是在页面进行的单击.双击.输入.滚动等操作,而webdriver也是一样,所以需要我们指定元素让webdriver进行单 ...
- python学习之——selenium元素定位
web自动化测试按步骤拆分,可以分为四步操作:定位元素,操作元素,获取返回结果,断言(返回结果与期望结果是否一致),最后自动出测试报告. 其中定位元素尤为关键,此篇是使用webdriver通过页面各个 ...
- python selenium 元素定位(三)
上两篇的博文中介绍了python selenium的环境搭建和编写的第一个自动化测试脚本,从第二篇的例子中看出来再做UI级别的自动化测试的时候,有一个至关重要的因素,那就是元素的定位,只有从页面上找到 ...
- selenium元素定位大全
要做自动化,首先要了解页面结构,要了解页面结构,就要了解页面元素的定位方法 在使用selenium webdriver进行元素定位时,通常使用findElement或findElements方法结合B ...
- selenium元素定位不到之iframe
我们在使用selenium的18中定位方式的时候,有时会遇到定位不上的问题,今天我们就来说说导致定位不上的其中一个原因---iframe 问题描述:通过firebug查询到相应元素的id或name等, ...
- selenium元素定位
在网页自动化测试中,我们要让程序自动模拟我们的点击.输入.悬浮.拖动等操作,完成我们的测试用例组. 输入.点击.打开这样的动词,已经包含在了selenium的方法中,可以直接调用(当然你也可以自己写) ...
随机推荐
- Win64 驱动内核编程-30.枚举与删除线程回调
枚举与删除线程回调 进程回调可以监视进程的创建和退出,这个在前面的章节已经总结过了.某些游戏保护的驱动喜欢用这个函数来监视有没有黑名单中的程序运行,如果运行则阻止运行或者把游戏退出.而线程回调则通常用 ...
- pr加字幕
选择免费字体 自由字体整理了免费的商用字体 安装字体 将下载好的.ttf文件,右键选择为所有用户安装 如果没有选择为所有用户安装,你在Arctime或者premiere中可能无法找到这个字体 而且想要 ...
- python之xlwt
python写excel----xlwt 写excel的拿点不在构造一个workbook的本身,二是填充的数据,不过这不在范围内,在写excel的操作中也有棘手的问题, 比如写入合并的单元格就是比较麻 ...
- 混部之殇-论云原生资源隔离技术之CPU隔离(一)
作者 蒋彪,腾讯云高级工程师,10+年专注于操作系统相关技术,Linux内核资深发烧友.目前负责腾讯云原生OS的研发,以及OS/虚拟化的性能优化工作. 导语 混部,通常指在离线混部(也有离在线混部之说 ...
- 用 edgeadm 一键安装边缘 K8s 集群和原生 K8s 集群
背景 目前,很多边缘计算容器开源项目在使用上均存在一个默认的前提:用户需要提前准备一个标准的或者特定工具搭建的 Kubernetes 集群,然后再通过特定工具或者其他方式在集群中部署相应组件来体验边缘 ...
- C++ primer plus读书笔记——第5章 循环和关系表达式
第5章 循环和关系表达式 1. cout.setf(ios_base::boolalpha); cout << (100 > 3) << endl;将输出true,而不是 ...
- OO_Unit2_多线程电梯
CSDN博客链接 一.第一次作业 1.需求分析 单部多线程傻瓜调度(FAFS)电梯 2.实现方案 输入接口解析 类似于Scanner,我们使用ElevatorInput进行阻塞式读取(第一次作业较简单 ...
- ssh-的搭建和使用
ssh的作用 : 可实现远程客户端登录服务器并对服务器的文件进行操作 ssh服务器的安装 farsight@ubuntu:~$ sudo apt-get install openssh-server ...
- MakeCode图形编程应用在micro:bit上的多工性能实测
1. 简述 本文不涉及对测试中所用到的设备或软件的推广. micro:bit 是一款由英国广播电视公司(BBC)为青少年编程教育设计,并由微软,三星,ARM,英国兰卡斯特大学等合作伙伴共同完成开发的微 ...
- jekyll-admin的搭建和使用
通过jekyll搭建好了自己的博客.写博客成为了日常,经过一段时间的摸索,发现jekyll-admin是个好东西,它是博客的后台管理系统,可以方便的管理和编写自己的博客 安装 运行命令gem inst ...