掌握 Selenium 元素定位,解决 Web 自动化测试痛点

参考链接
https://mp.weixin.qq.com/s/nHzjGQ030M8FvYI_AfQEfw

图片.png

Selenium架构

client:每个语言都有自己的库,提供不同的 API 供用户去调用完成相关的自动化测试行为;这里调用有关 web 自动化的 API 到 selenium 的 server
selenium:用于将接收到的请求传给浏览器的driver,实施调用,实际上 selenium 就是浏览器driver的一个封装
driver:针对浏览器的一个驱动引擎,每个浏览器都有自己的驱动(一般由各个浏览器厂商提供),可以通过驱动浏览器的API来完成对应操作
browser:浏览器

Selenium核心组件

selenium webdriver client (目前主要使用的,依赖于drivers)
selenium drivers (浏览器驱动,被webdriver client 所依赖)
selenium1 selenium-rc (已弃用)
selenium IDE (入门录制工具-本人不常用,仅了解过)
selenium grid (可操纵浏览器集群,也可操作App)

Selenium安装

第一步:组件安装

安装浏览器 :web自动化,没浏览器好像说不过去了,先装浏览器是必须的
安装selenium driver,加入环境变量path :环境变量,老生常谈的问题了
安装selenium-client :安装到这步后就可以开始web自动化了,不同语言的根据需要进行安装,如Java的可以使用maven,目前建议使用稳定版本的3.141.59:
安装selenium-ide : 新手入门,我在这里就不去演示了,需要入门了解的小伙伴可以查阅资料哈~

'''
//此处为Selenium-client代码
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.141.59</version>
</dependency>
'''

第二步:ChromeDriver下载

笔者这里主要用的是Chrome浏览器,所以就以Chrome为例 。
1)先去到selenium官网的下载中心www.seleniumhq.org/download/;往下翻,翻到如下图的位置:

图片.png

2)进去后找到与你当前Chrome浏览器版本对应的driver版本,下载对应系统的driver(需要梯子,如果没有继续往下看)
图片.png

图片.png

如果你没有梯子,无法去官网下载driver的话,这里提供一个淘宝的镜像,在国内的网络就可以直接下载 https://npm.taobao.org/mirrors/chromedriver

3)下载完成后解压到自己指定的路径即可,别忘了将路径添加到环境变量中(这里以Mac为例)
echo 'export PATH=PATH:chrome' >> ~/.bash_profile

chrome改为chromedriver的存放路径

$ tail -1 ~/.bash_profile

元素定位

首先,我们需要认识元素。元素是可识别区分的属性。
Selenium的WebDriver一共提供了九种定位方法,其中最常用的是前八种,先来看看在Java中的对应关系。


图片.png

如上表所示,web自动化就是靠着HTML的各种标签、属性等来定位元素来进行操作:
同样的,元素自身也有id、classname、tagname、name等属性可用于区分定位;
同样的,元素自身也可以通过Xpath和CSS这种标签的层级位置来定位元素。
同样的,元素也可以通过与其相关的元素来进行定位,我们就可以用CSS或Xpath来进行父子,兄弟等节点位置的方式来进行定位了。

总结-定位元素的方法

1.By ID - 身份证

现在我们要定位testerhome首页右上角的欢迎,如下图:
打开Chrome开发者工具,选中元素进行查看,元素是有id的,可以根据id来定位:


图片.png

WebDriver driver = new ChromeDriver();
driver.findElement(By.id("cornertip"));
driver.findElement(By.cssSelector("#cornertip")); //CSS
小技巧:我们可以在Chrome的开发者工具中Control+F搜索框中对我们要定位的元素进行搜索来确认定位是否正确,支持CSS和xpath,如上图所示

2.By Class Name - 别名

要定位testerhome首页的搜索框,就可以根据ClassName,如下图:


图片.png

WebDriver driver = new ChromeDriver();
driver.findElement(By.className("form-control"));
driver.findElement(By.cssSelector(".form-control")); //CSS

3.By Name - 姓名

依然定位首页的搜索框,可通过name和CSS定位:


图片.png

WebDriver driver = new ChromeDriver();
driver.findElement(By.className("q"));
driver.findElement(By.cssSelector("[name='q']")); //CSS

4.By Tag Name

依然是定位testerhome首页的搜索框,通过tagname :input来定位


图片.png

WebDriver driver = new ChromeDriver();
driver.findElement(By.tagName("input"));
driver.findElement(By.cssSelector("input")); //CSS

5.By Link Text

定位testerhome首页一周最热的帖子,通过linktest和CSS:


图片.png

WebDriver driver = new ChromeDriver();
driver.findElement(By.linkText("[深圳][头条] 招聘测试 leader"));
driver.findElement(By.cssSelector("a[title='[深圳][头条] 招聘测试 leader']"));

6. By Partial Link Text

定位testerhome首页一周最热的帖子,通过partialLinkText和CSS


图片.png

WebDriver driver = new ChromeDriver();
driver.findElement(By.partialLinkText("[深圳][头条]"));
driver.findElement(By.cssSelector("[title~='[深圳][头条]']")); //CSS

7.Using JavaScript

有时候我们的页面元素被遮挡导致无法定位,需要滚动屏幕进行可视化,便可以用JS来操作:
((JavascriptExecutor)(driver)).executeScript("window.scroll(0, 1200)");

8.By Xpath

XPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历,
而HTML又正好可以看做是XML的一种实现,因此我们便可以用xpath来定位元素啦


图片.png

举几个简单的栗子
1)绝对路径定位:
做测试开发或者有编程经验的小伙伴一定对绝对路径不陌生,通过绝对路径就是使用元素在页面上的完整路径。
还是以定位一周内的最热门帖子为例,在Chrome浏览器的开发者工具栏中,找到要定位元素的HTML位置,右击会出现Copy full Xpath,点击它


图片.png

然后我们把复制到的内容黏贴后如下:
/html/body/div[2]/div[2]/div/div[2]/div[1]/div[2]/div[1]/div/a
写到代码里就是这样:
WebDriver driver = new ChromeDriver();
driver.findElement(By.xpath("/html/body/div[2]/div[2]/div/div[2]/div[1]/div[2]/div[1]/div/a"));

可以用又臭又长来形容了,那么细心的小伙伴会发现还有一个Copy xpath,复制黏贴后内容如下:
//*[@id="main"]/div/div[2]/div[1]/div[2]/div[1]/div/a
看起来好像简化了点,还用上了xpath的语法,但是实际上也没优化多少,依然是通过标签的层级关系,从最外层一级一级的往下找,也不是很可取;

其实不可取的最主要原因还是这种绝对路径的方式在实际自动化过程中很不稳定,界面的位置发生任何一丢丢的变化,那元素的绝对路径就很可能变了,也就无法准确定位了。

因此我们就要用元素的属性或者属性和层级关系相结合的方式来定位,这样就算页面变化,只要变化不是非常大,依然可以通过元素的属性和相对的位置来进行定位,
受页面位置变化的影响就要小的多了。

2)元素属性定位:
定位testerhome首页的欢迎,利用xpath语法通过id来定位:


图片.png

WebDriver driver = new ChromeDriver();
driver.findElement(By.xpath("//div[@id='c-button']"));
语法解释://div表示从当前页面的div标签开始匹配,@id表示用id属性值,=后面跟着具体的id值

3)属性和层级关系定位:
上面的通过属性定位完全可以用WebDriver的API或者CSS搞定,xpath最大的价值就是上面说的当元素没有直接可定位的属性时,它的价值才得以完美体现:

现在我们要定位”七日最热 Top10“这个标题,它只有class属性,我们按照className来进行定位会发现如下情况:

图片.png

没错,出现了10个可被定位到的元素,因为有很多的标题都有相同的classname,并且没有其他如id,name等属性了;
没办法了,我们就要往上找,我们发现往上2个div标签节点,classname为”col-md-3 home-side-bar“的标签节点是唯一的:

图片.png

现在我们就利用Xpath先定位到唯一的那个class,然后往下找两层div,再取两层后div中的第一个就可以了

WebDriver driver = new ChromeDriver();
driver.findElement(By.xpath("//*[@class='col-md-3 home-side-bar']/div[1]/div[1]"));

4)使用Xpath运算符定位:
Xpath还支持运算符,如果元素的一个属性无法定位,需要使用多个属性时可以使用Xpath运算符将多个属性连接起来一起定位
Xpath常用运算符:


图片.png

现在需要定位testhome社区首页一篇最新帖子的作者,作者名为“乌云乌云快走开” 如果我们只依靠className的话会发现有28个相同属性的元素,如下图:


图片.png

继续观察会发现还有一个叫做data-name的属性,属性值就是作者的姓名,我们通过and符将两个属性连接后便发现可以精准定位到指定元素了:
图片.png

WebDriver driver = new ChromeDriver();
driver.findElement(By.xpath("//a[@class='user-name' and @data-name='乌云乌云快走开']"));

5)使用Xpath函数定位:
Xpath还提供了很多函数来供我们更灵活的定位,这里以我常用的一个contains函数为例

我们依旧来定位testerhome首页七日最热贴的首贴“[深圳][头条] 招聘测试 leader”,通过对DOM的分析可以看到title属性的内容就是帖子的标题,我们用此属性值的一部分来作为定位条件:

图片.png

WebDriver driver = new ChromeDriver();
driver.findElement(By.xpath("//*[contains(@title,'[深圳][头条]')]"));
关于Xpath的语法使用还有很多,包括还有很多函数,具体的可参考W3C进行学习:https://www.w3school.com.cn/xpath/xpath_syntax.asp

9.By CSS
Web页面的样式通常保存在外部的 .css 文件中。通过仅仅编辑一个简单的 CSS 文档,外部样式表使你有能力同时改变站点中所有页面的布局和外观。因此我们可以利用CSS的选择器来定位页面绑定了属性的元素,从而为我们的selenium所用

从上面的文章一路看下来的小伙伴应该发现了,在介绍xpath之前的定位方式时,都另外还写了一个CSS的定位方式,没错,就是它,没注意的小伙伴可以返回去看一看;

推荐使用CSS: CSS也是我们在Web自动化中最推荐使用的一种方式,原因又如下几种:

例如id这种元素在一个页面中可能并不唯一,并且很有可能是前端的框架自动生成的,研发人员并未对其进行维护,随时可能变;而CSS是前端开发最常用的一种维护方式,对于我们开发和维护自动化用例也更为清晰和方便
大部分定位都可以用CSS来解决
CSS的写法相较于Xpath要更为简洁

常用的CSS选择器语法:


图片.png

图片.png

先将前面已经演示过的CSS语法在这来个小的汇总:
通过id
WebDriver driver = new ChromeDriver();
driver.findElement(By.cssSelector("#cornertip")); //CSS

通过className
WebDriver driver = new ChromeDriver();
driver.findElement(By.cssSelector(".form-control"));

通过name
WebDriver driver = new ChromeDriver();
driver.findElement(By.cssSelector("[name='q']"));

通过tag name
WebDriver driver = new ChromeDriver();
driver.findElement(By.cssSelector("input"));

通过link text
WebDriver driver = new ChromeDriver();
driver.findElement(By.cssSelector("a[title='[深圳][头条] 招聘测试 leader']"));

通过partialLinkText
WebDriver driver = new ChromeDriver();
driver.findElement(By.cssSelector("[title~='[深圳][头条]']"));

另外CSS也可以将属性和层级关系组合在一起进行使用,现在我们以这种组合方式来定位testerhome社区置顶帖的第一篇帖子:


图片.png

WebDriver driver = new ChromeDriver();
driver.findElement(By.cssSelector("简要说明: .panel-heading:class值为panel-heading +div : 后面紧接着的div >div:后面所有子的div div.topic-20857:class名为topic-20857的div标签

更多细节和用法可参考W3C进行学习:
https://www.w3school.com.cn/cssref/css_selectors.asp

参考文档:
selenium官网:https://selenium.dev/documentation/en/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,884评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,212评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,351评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,412评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,438评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,127评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,714评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,636评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,173评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,264评论 3 339
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,402评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,073评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,763评论 3 332
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,253评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,382评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,749评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,403评论 2 358