推开Web自动化的大门到达“犯罪现象”-侦破selenium架构、环境安装及常用元素定位方法

673 阅读13分钟

有关Selenium的介绍在网上实在是太多了,总结起来就是一个目前在web自动化方面运用最为广泛的一个开源自动化测试框架

1、Selenium架构

在这里插入图片描述

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

2、Selenium核心组件

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

3、Selenium的安装

3.1组件安装:

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

3.2 ChromeDriver下载

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

在这里插入图片描述
2)进去后找到与你当前Chrome浏览器版本对应的driver版本,下载对应系统的driver(需要梯子,如果没有继续往下看)
在这里插入图片描述
在这里插入图片描述
如果你没有梯子,无法去官网下载driver的话,这里提供一个淘宝的镜像,在国内的网络就可以直接下载 npm.taobao.org/mirrors/chr…
3)下载完成后解压到自己指定的路径即可,别忘了将路径添加到环境变量中(这里以Mac为例)

$ echo 'export PATH=$PATH:/Users/qinzhen/Documents/TestDev/WebAuto/webdrivers/chromedrivers/chrome_77/' >> ~/.bash_profile
$ tail -1 ~/.bash_profile
export PATH=$PATH:/Users/qinzhen/Documents/TestDev/WebAuto/webdrivers/chromedrivers/chrome_77/

4、元素定位

元素定位是做UI自动化最基础也是最重要的部分之一了,算是web自动化的大门,推开这扇门走进web自动化的世界

4.1 推开大门,到达“犯罪现象”-认识元素

SeleniumWebDriver一共提供了九种定位方法,其中最常用的是前八种,先来看看在Java中的对应关系

定位方法 对应API 说明
id By.id 通过id号
class name By.className 通过class属性值
tag name By.tagName 通过tag属性值
name By.name 通过name属性值
link text By.linkText 通过链接的文本信息
partial link text By.partialLinkText 通过部分匹配的链接文本信息
css By.cssSelector 通过CSS
xpath By.xpath 通过xpath
javascript ((JavascriptExecutor)driver).executeScript 通过执行JavaScript定位元素,返回WebElement对象
  • 如上表所示,web自动化就是靠着HTML的各种标签、属性等来定位元素来进行操作,那么这些定位方式怎么理解?我们可以参考一个犯罪案例

    警察正在抓捕一名人犯罪嫌疑人,要确认犯罪嫌疑人的身份就可以根据嫌疑人的姓名、别名、指纹、身份证号、手机号等可识别区分的属性;同样的,元素自身也有idclassnametagnamename等属性可用于区分定位;

    此嫌疑人的反侦察能力比较强,隐藏了自己的身份特征,无法根据其自身的属性进行定位,那么就可以根据其经常出没的场所来进行定位抓捕,例如去某省某市的某个酒吧里,去某县某村某号的一个住所去;同样的,元素自身也可以通过XpathCSS这种标签的层级位置来定位元素。

    到目前为止,嫌烦依然在逃,为了躲避侦查,曾经的常去场所都不再接触,高手!这是高手!苦苦的等待,最终办案民警们终于有了线索(接下来该办案民警出场讲述转机了~):由于犯罪嫌疑人是个大孝子且十分疼爱自己的妻儿,于是在某个地方偷偷的给父母通了电话,去学校见了妻儿;最终根据其家人提供的信息暴露自己,被定位抓获!同样的,元素也可以通过与其相关的元素来进行定位,我们就可以用CSSXpath来进行父子,兄弟等节点位置的方式来进行定位了

4.2 案件告破,案情总结-定位方法的使用

Warning! 下面在介绍各种定位方式的时候还会顺便补充CSS的定位方式作为对比,首次接触的话可能会因为看不懂而引起不适,不用担心,可以先忽略,后面会专门介绍CSS的,待了解了CSS定位方式后再回来学习

4.2.1 By ID——身份证
  • 现在我们要定位testerhome首页右上角的欢迎,如下图:
    在这里插入图片描述
  • 打开Chrome开发者工具,选中元素进行查看,元素是有id的,可以根据id来定位:
    在这里插入图片描述
    WebDriver driver = new ChromeDriver();
    driver.findElement(By.id("cornertip"));
    driver.findElement(By.cssSelector("#cornertip"));  //CSS
    

小技巧:我们可以在Chrome的开发者工具中Control+F搜索框中对我们要定位的元素进行搜索来确认定位是否正确,支持CSSxpath,如上图所示

4.2.2 By Class Name——别名
  • 要定位testerhome首页的搜索框,就可以根据ClassName,如下图:
    在这里插入图片描述
    WebDriver driver = new ChromeDriver();
    driver.findElement(By.className("form-control"));
    driver.findElement(By.cssSelector(".form-control"));  //CSS
    
4.2.3 By Name——姓名
  • 依然定位首页的搜索框,可通过nameCSS定位:
    在这里插入图片描述
    WebDriver driver = new ChromeDriver();
    driver.findElement(By.className("q"));
    driver.findElement(By.cssSelector("[name='q']"));  //CSS
    
4.2.4 By Tag Name
  • 依然是定位testerhome首页的搜索框,通过tagnameinput来定位
    在这里插入图片描述
    WebDriver driver = new ChromeDriver();
    driver.findElement(By.tagName("input"));
    driver.findElement(By.cssSelector("input"));  //CSS
    
4.2.5 By Link Text
  • 定位testerhome首页一周最热的帖子,通过linktestCSS:
    在这里插入图片描述
    WebDriver driver = new ChromeDriver();
    driver.findElement(By.linkText("[深圳][头条] 招聘测试 leader"));
    driver.findElement(By.cssSelector("a[title='[深圳][头条] 招聘测试 leader']")); //CSS
    
4.2.6 By Partial Link Text
  • 定位testerhome首页一周最热的帖子,通过partialLinkTextCSS
    在这里插入图片描述
WebDriver driver = new ChromeDriver();
driver.findElement(By.partialLinkText("[深圳][头条]"));
driver.findElement(By.cssSelector("[title~='[深圳][头条]']"));  /CSS
4.2.7 Using JavaScript

有时候我们的页面元素被遮挡导致无法定位,需要滚动屏幕进行可视化,便可以用JS来操作:

((JavascriptExecutor)(driver)).executeScript("window.scroll(0, 1200)");
4.2.8 By Xpath

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

  • 问题:一般刚开始学定位的时候很多人都会想,都有了上面那么多种定位方式了,还要xpath干吗?感觉还挺复杂的样子(和其他的定位方式相比却是要复杂那么一丢丢)~ 答: 那是因为并不是所有的元素都“如您所愿”,就如上面警察抓捕罪犯的例子,有时候元素并不能直接提供给我们想要的定位属性

  • 常用路径表达式:

    表达式 描述
    nodename 选取此节点的所有子节点。
    / 从根节点选取。
    // 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
    . 选取当前节点。
    .. 选取当前节点的父节点。
    @ 选取属性。
  • 举几个简单的栗子 1)绝对路径定位

    做测试开发或者有编程经验的小伙伴一定对绝对路径不陌生,通过绝对路径就是使用元素在页面上的完整路径、

    还是以定位一周内的最热门帖子为例,在Chrome浏览器的开发者工具栏中,找到要定位元素的HTML位置,右击会出现Copy full Xpath,点击它

    在这里插入图片描述
    然后我们把复制到的内容黏贴后如下:

    /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来定位:
    在这里插入图片描述
    WebDriver driver = new ChromeDriver();
    driver.findElement(By.xpath("//div[@id='c-button']"));
    
    语法解释://div表示从当前页面的div标签开始匹配,@id表示用id属性值,=后面跟着具体的id

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

  • 现在我们要定位”七日最热 Top10“这个标题,它只有class属性,我们按照className来进行定位会发现如下情况:
    在这里插入图片描述
    没错,出现了10个可被定位到的元素,因为有很多的标题都有相同的classname,并且没有其他如idname等属性了; 没办法了,我们就要往上找,我们发现往上2个div标签节点,classname为”col-md-3 home-side-bar“的标签节点是唯一的:
    在这里插入图片描述
    现在我们就利用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常用运算符

    运算符 描述 实例 返回值
    | 计算两个节点集 //book | //cd 返回所有拥有 book 和 cd 元素的节点集
    or price=9.80 or price=9.70 如果 price 是 9.80,则返回 true。如果 price 是 9.50,则返回 false。
    and price>9.00 and price<9.90 如果 price 是 9.80,则返回 true。如果 price 是 8.50,则返回 false。
  • 现在需要定位testhome社区首页一篇最新帖子的作者,作者名为“乌云乌云快走开” 如果我们只依靠className的话会发现有28个相同属性的元素,如下图:

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

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

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

  • 我们依旧来定位testerhome首页七日最热贴的首贴“[深圳][头条] 招聘测试 leader”,通过对DOM的分析可以看到title属性的内容就是帖子的标题,我们用此属性值的一部分来作为定位条件:
    在这里插入图片描述
    WebDriver driver = new ChromeDriver();
    driver.findElement(By.xpath("//*[contains(@title,'[深圳][头条]')]"));
    

关于Xpath的语法使用还有很多,包括还有很多函数,具体的可参考W3C进行学习: www.w3school.com.cn/xpath/xpath…

4.2.9 By CSS

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

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

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

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

常用的CSS选择器语法:

选择器 例子 例子描述
.class .intro 选择 class="intro" 的所有元素。
#id #firstname 选择 id="firstname" 的所有元素。
* * 选择所有元素。
element p 选择所有 <p> 元素。
element,element div,p 选择所有 <div> 元素和所有 <p> 元素。
element element div p 选择 <div> 元素内部的所有 <p> 元素。
element>element div>p 选择父元素为 <div> 元素的所有 <p> 元素。
element+element div+p 选择紧接在 <div> 元素之后的所有 <p> 元素。
[attribute] [target] 选择带有 target 属性所有元素。
[attribute=value] [target=_blank] 选择 target="_blank" 的所有元素。
[attribute~=value] [title~=flower] 选择 title 属性包含单词 "flower" 的所有元素。

先将前面已经演示过的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社区置顶帖的第一篇帖子:
    在这里插入图片描述
WebDriver driver = new ChromeDriver();
driver.findElement(By.cssSelector(".panel-heading+div>div>div.topic-20857")); 

简要说明: .panel-heading:class值为panel-heading +div : 后面紧接着的div >div:后面所有子的div div.topic-20857:class名为topic-20857的div标签

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

参考文档: selenium官网:www.seleniumhq.org/docs/03_web…