zoukankan      html  css  js  c++  java
  • 【WEB自动化】【第一节】【Xpath和CSS元素定位】

    目前自动化测试开始投入WEB测试,使用RF及其selenium库,模拟对WEB页面进行操作,此过程中首先面对的问题就是对WEB页面元素的定位,几乎所有的关键字都需要传入特定的WEB页面元素,因此掌握常用的WEB元素定位方法是WEB测试人员最基本的技能。本文主要结合个人在实践中的应用,将常用的XPATHCSS的元素定位方法进行汇总和总结,以便于引导WEB测试人员快速入门。

    1. HTML基础知识

    前端页面主要使用HTML进行元素排版,使用CSS进行样式设计,使用JS实现交互。在WEB测试中,熟悉HTML文档基本架构对后续的元素定位是不可或缺的。

    一张图展示HTML基本架构:

     

    HTML 的结构就是树形结构,HTML 是根节点,所有的其他元素节点都是从根节点发出的。其他的元素都是这棵树上的节点Node,每个节点还可能有属性和文本。而路径就是指某个节点到另一个节点的路线。

    节点之间存在各种关系:

    • 父节点(Parent)HTML body head 节点的父节点;
    • 子节点(Child)head body HTML 的子节点;
    • 兄弟节点(Sibling):拥有相同的父节点,head body 就是兄弟节点。title div 不是兄弟,因为他们不是同一个父节点。
    • 祖先节点(Ancestor)body form 的祖先节点,爷爷辈及以上
    • 后代节点(Descendant)form HTML 的后代节点,孙子辈及以下

    更多的HTML知识需要查阅相关资料和书籍。

    2. XPATH方式进行WEB元素定位

     2.1 XPATH基本定位语法

    定位语法主要依赖于以下特殊符号:

    表达式

    说明

    举例

    /

    从根节点开始选取

    /html/div/span

    //

    从任意节点开始选取

    //input

    .

    选取当前节点

    ..

    选取当前节点的父节点

    //input/.. 会选取 input 的父节点

    @

    选取属性,或者根据属性选取

    //input[@data] 选取具备 data 属性的 input 元素
    //@data 选取所有 data 属性

    *

    通配符,表示任意节点或任意属性

    2.2 绝对路径:

    Xpath 中最直观的定位策略就是绝对路径。可以通过浏览器的开发者工具copyWEB元素的绝对路径,绝对路径是从根节点/html开始往下,一层层的表示出来直到需要的节点为止。以监控平台的WEB首页的登录按钮为例:

    /html/body/div[2]/div/div[2]/form/div[5]/a[2]/span

    这就是一个绝对路径。

    2.3 相对路径:

    除了绝对路径,Xpath 中更常用的方式是相对路径定位方法,以“//”开头。相对路径可以从任意节点开始,一般我们会选取一个可以唯一定位到的元素开始写,可以增加查找的准确性。

    //a[@onclick="doLogin();return false;"]/span


    2.4 元素属性定位

    属性定位是通过 @ 符号指定需要使用的属性。

    根据元素是否具备某个属性查找元素://a[@onclick]

    根据属性是否等于某值查找元素://a[@onclick="doLogin();return false;"]

    注意,属性值必须要加引号,单双引号都可以。

    实践中最为常用的属性当属idnameclass了,且前两个属性一般作为元素的唯一标示符使用,因此通过idname属性进行元素定位,通常表示式简单且运行速度快。

    例如定位WEB首页中的用户名输入框和密码输入框,可用id进行定位:

    //input[@id="loginname"]

    //input[@id="loginpsw"]

    2.5 层级属性结合定位

    遇到某些元素无法精确定位的时候,可以查找其父级及其祖先节点,找到有确定的祖先节点后通过层级依次向下定位。

    根据层级向下找://div/a[@onclick="doLogin();return false;"]/span

    查找某元素内部的所有元素://div//a[@onclick]

    第二个双斜杠,表示选取内部所有的满足条件的a,不关心层级关系。

    使用星号找不特定的元素://*[@*="doLogin();return false;"],这里会找到登录按钮。

    使用..从下往上找,根据子节点查找其父节点://span[text()="Login"]/..

    注意最后的两个点,找到 span 节点的上级节点,如果还要再往上再加 /..

    找同级节点://span[text()="Login"]/../../a
        树形结构中,兄弟节点之间的关系是通过父节点建立起来的。所以可以先找到父节点,再通过父节点找同级节点。

    2.6 使用谓语定位

    谓语是 Xpath 中用于描述元素位置的语句。主要有数字下标、最后一个子元素last()、元素下标函数position()
        ①使用下标的方式:此处有坑,见疑难问题解决。

    注意:Xpath 中的下标从 1 开始。

    ②查找最后一个子元素://form/div[last()]

    ③查找倒数第2个子元素://form/div[last()-1]

    ④使用 position() 函数,选取 from 下第2div//form/div[position()=2]

    ⑤使用 position() 函数,选取form下下标大于2div//form/div[position()>2]或//form/div[position()>=3]

    2.7 使用逻辑运算符

    如果元素的某个属性无法精确定位到这个元素,我们还可以用逻辑运算符 and or 连接多个属性进行定位,也可以用 | 连接多个路径

    ①使用 and //input[@id="loginname" and @type="text"]

    ②使用 or //span[text()="Login" or text()="登录"]

    ③使用 | //input[@id="loginname"] | //input[@id="loginpsw"]

    2.8 使用文本定位

    使用文本定位,是 Xpath 中的一大特色。在自动化测试中,为了让代码的可读性更高,可以使用文本的方式需要用到 Xpath 中的函数 text() string() ,注意是函数,所以括号不能少。

    text():当前元素节点包含的文本内容,而不会包含节点元素的文本内容

    string():当前元素节点内部所有节点元素的文本内容,如有多个节点元素包含多个文本内容,则按层级顺序将各节点元素的文本内容进行拼接后返回

    例如,我们的WEB首页中,登录按钮元素周围的HTML代码如下:

        <a href="#" onclick="doLogin();return false;" style="float: right;color: white;">

            <span>Login</span>

            <i class="icon-circle-arrow-right"></i>

        </a>

    text()方法://span[text()="Login"]能定位到按钮区域,//a[text()="Login"]则不能;

    string()方法://span[string()="Login"]和//a[string()="Login"]均能定位到按钮区域。

    2.9 使用部分匹配函数

    Xpath中提供了几个函数,用来进行部分匹配。

    函数

    说明

    举例

    contains

    选取属性或者文本包含某些字符

    //div[contains(@id, 'data')] 选取 id 属性包含 data div 元素
    //div[contains(string(), '支付宝')] 选取内部文本包含支付宝div 元素

    starts-with

    选取属性或者文本以某些字符开头

    //div[starts-with(@id, 'data')] 选取 id 属性以 data 开头的 div 元素
    //div[starts-with(string(), '银联')] 选取内部文本以银联开头的 div 元素

    ends-with

    选取属性或者文本以某些字符开头

    //div[ends-with(@id, 'require')] 选取 id 属性以 require 结尾的 div 元素
    //div[ends-with(string(), '支付')] 选取内部文本以支付结尾的 div 元素


        其中,ends-with()仅在xpath2.0中支持,而目前RFselenium库、chrome浏览器都只支持xpath1.0,以查找WEB首页的密码输入框元素(包含id"loginpsw")为例:

    //*[contains(@id, "loginpsw")]        能匹配到

    //*[starts-with(@id, "loginpsw")]    能匹配到

    //*[ends-with(@id, "loginpsw")]       不能匹配到

    //*[substring(@id, string-length(@id) - string-length('loginpsw') +1) = 'loginpsw']   能匹配到,实现了ends-with功能

    2.10 实践中疑难问题解决:

    ①通过Xpath查找某个节点下某一级下的子节点,而不关注具体层级:

    //div[@id="hisevent"]//button[@id="event_searchBT"]  查找指定div下任一子级的特定button(使用//

    ②通过Xpath如何获取文档中第几个匹配节点://name[3]表示所有位置3name(//name)[3]才是你要的,所有name的第3个。

    (//div[@id="hisevent"]//input)[2]

    //div[@id="hisevent"]//input[position()=2]

    需要在所有匹配中定位时,先用()括起来,或使用postion()函数。

    ③通过xpath由子节点元素查找父节点元素或祖先节点:

    //a[span[text()="Login"]]

    //div[@id="hisevent"]//table[tbody[contains(@id, "list")]]

    参考:https://www.jianshu.com/p/6a0dbb4e246a

          https://www.cnblogs.com/hanmk/p/8997786.html

    3. CSS方式进行WEB元素定位

    3.1 CSS选择器基础知识

    CSS选择器分4大类:基本选择器、属性选择器、伪类选择器、伪元素选择器。

    注意:选择器总是从左至右解析,不要私自添加()优先运算

    其中基本选择器主要包括以下四类符号:

    1) 标签选择器:使用标签名称进行标识,如divap

    2) ID选择器:使用#进行标识;

    3) 类选择器:使用.进行标识;

    4) 通配符选择器:使用*进行标识。

    其余属性选择器、伪类选择器、伪元素选择器都可归为扩展选择器。

    选择器

    例子

    例子描述

    CSS版本

    选择器分类

    .class

    .intro

    选择 class="intro" 的所有元素。

    1

    基本选择器

    #id

    #firstname

    选择 id="firstname" 的所有元素。

    1

    基本选择器

    *

    *

    选择所有元素。

    2

    基本选择器

    element

    p

    选择所有 <p> 元素。

    1

    基本选择器

    element,element

    div,p

    选择所有 <div> 元素和所有 <p> 元素。

    1

    基本选择器

    element element

    div p

    选择 <div> 元素内部的所有 <p> 元素。

    1

    基本选择器

    element>element

    div>p

    选择父元素为 <div> 元素的所有 <p> 元素。

    2

    基本选择器

    element+element

    div+p

    选择紧接在 <div> 元素之后的所有 <p> 元素。

    2

    基本选择器

    [attribute]

    [target]

    选择带有 target 属性所有元素。

    2

    属性选择器

    [attribute=value]

    [target=_blank]

    选择 target="_blank" 的所有元素。

    2

    属性选择器

    [attribute~=value]

    [title~=flower]

    选择 title 属性包含单词 "flower" 的所有元素。

    2

    属性选择器

    [attribute|=value]

    [lang|=en]

    选择 lang 属性值以 "en" 开头的所有元素。

    2

    属性选择器

    :link

    a:link

    选择所有未被访问的链接。

    1

    伪类选择器

    :visited

    a:visited

    选择所有已被访问的链接。

    1

    伪类选择器

    :active

    a:active

    选择活动链接。

    1

    伪类选择器

    :hover

    a:hover

    选择鼠标指针位于其上的链接。

    1

    伪类选择器

    :focus

    input:focus

    选择获得焦点的 input 元素。

    2

    伪类选择器

    :first-letter

    p:first-letter

    选择每个 <p> 元素的首字母。

    1

    伪元素选择器

    :first-line

    p:first-line

    选择每个 <p> 元素的首行。

    1

    伪元素选择器

    :first-child

    p:first-child

    选择属于父元素的第一个子元素的每个 <p> 元素。

    2

    伪元素选择器

    :before

    p:before

    在每个 <p> 元素的内容之前插入内容。

    2

    伪元素选择器

    :after

    p:after

    在每个 <p> 元素的内容之后插入内容。

    2

    伪元素选择器

    :lang(language)

    p:lang(it)

    选择带有以 "it" 开头的 lang 属性值的每个 <p> 元素。

    2

    伪元素选择器

    element1~element2

    p~ul

    选择前面有 <p> 元素的每个 <ul> 元素。

    3

    基本选择器

    [attribute^=value]

    a[src^="https"]

    选择其 src 属性值以 "https" 开头的每个 <a> 元素。

    3

    属性选择器

    [attribute$=value]

    a[src$=".pdf"]

    选择其 src 属性以 ".pdf" 结尾的所有 <a> 元素。

    3

    属性选择器

    [attribute*=value]

    a[src*="abc"]

    选择其 src 属性中包含 "abc" 子串的每个 <a> 元素。

    3

    属性选择器

    :first-of-type

    p:first-of-type

    选择属于其父元素的首个 <p> 元素的每个 <p> 元素。

    3

    伪元素选择器

    :last-of-type

    p:last-of-type

    选择属于其父元素的最后 <p> 元素的每个 <p> 元素。

    3

    伪元素选择器

    :only-of-type

    p:only-of-type

    选择属于其父元素唯一的 <p> 元素的每个 <p> 元素。

    3

    伪元素选择器

    :only-child

    p:only-child

    选择属于其父元素的唯一子元素的每个 <p> 元素。

    3

    伪元素选择器

    :nth-child(n)

    p:nth-child(2)

    选择属于其父元素的第二个子元素的每个 <p> 元素。

    3

    伪元素选择器

    :nth-last-child(n)

    p:nth-last-child(2)

    同上,从最后一个子元素开始计数。

    3

    伪元素选择器

    :nth-of-type(n)

    p:nth-of-type(2)

    选择属于其父元素第二个 <p> 元素的每个 <p> 元素。

    3

    伪元素选择器

    :nth-last-of-type(n)

    p:nth-last-of-type(2)

    同上,但是从最后一个子元素开始计数。

    3

    伪元素选择器

    :last-child

    p:last-child

    选择属于其父元素最后一个子元素每个 <p> 元素。

    3

    伪元素选择器

    :root

    :root

    选择文档的根元素。

    3

    伪类选择器

    :empty

    p:empty

    选择没有子元素的每个 <p> 元素(包括文本节点)。

    3

    伪类选择器

    :target

    #news:target

    选择当前活动的 #news 元素。

    3

    伪类选择器

    :enabled

    input:enabled

    选择每个启用的 <input> 元素。

    3

    伪类选择器

    :disabled

    input:disabled

    选择每个禁用的 <input> 元素

    3

    伪类选择器

    :checked

    input:checked

    选择每个被选中的 <input> 元素。

    3

    伪类选择器

    :not(selector)

    :not(p)

    选择非 <p> 元素的每个元素。

    3

    伪类选择器

    ::selection

    ::selection

    选择被用户选取的元素部分。

    3

    伪类选择器

    参考:https://www.w3school.com.cn/cssref/css_selectors.ASP

          https://blog.csdn.net/luanpeng825485697/article/details/76935715

          https://blog.csdn.net/DYD850804/article/details/80997251

    3.2 CSS选择器实战

    下面以WEB的历史操作记录页面为例进行实践。

    直接给出查找此页面中结束时间选框的定位语句,再进行分析:

    div#hisevent input.form-control.input-medium[type="text"][onfocus*="WdatePicker"]:nth-child(2)

    (可在文本编辑器放大查看)

    ①先从任意div标签的元素出发查找,直到其具备id属性(#)值为hisevent

    ②查找①的div元素内部的input标签元素,使用空格进行隔离。此处需要注意,关于标签层级,CSS有两个最基本的查找语法:ele1>ele2ele1 ele2,类似于Xpath///,前者代表ele1ele2为父子节点关系,后者代表ele1内部包含ele2,而不在乎具体层级;

    ③查找的input元素须包含值为"form-control input-medium"的类(class)属性,使用圆点进行标识。这里注意,该元素的class的值中包含一个空格,在选择器表达式里,空格已经有了具体含义;在书写包含空格的class属性时,直接将空格替换为圆点即可事实上class属性值中的空格表示此元素能匹配多个class样式表,即样式复用,同时具有先后关系。参考:

    https://blog.csdn.net/liuhehe123/article/details/81608225

    https://www.cnblogs.com/guxin/p/css-multi-class-selector.html

    ④在找到包含指定类的input标签元素后,进一步通过属性进行筛选,最基础的表达式为[name=value],实践中发现value用不用引号包围均可;如果想通过多个属性(“与”的关系)来精确定位元素,可以直接连接多个属性表达式,如[type="text"][onfocus*="WdatePicker"]。参考:

    https://cloud.tencent.com/developer/ask/27977

    ⑤通过以上一番操作,定位到的元素仍然有两个,分别是起始时间框和结束时间框,二者位于同一级,是兄弟节点关系,要定位到第二个节点,使用:nth-child(2)即可,其原意为归属于父节点的第n个子节点。对同级节点定位方法参考:

    https://blog.csdn.net/hcwbr123/article/details/80846862

    3.3 实践中疑难问题解决:

    ①属性选择器部分匹配:~= |= *= ^= $= 的区别:

     ~= 、|= 按完整单词进行匹配,完整单词指整个的单词、以空格或-分隔的单词;

     *= ^= $= 按字符串进行匹配,显然此类方法更易用且更常用。举例

    div#hisevent button[onclick^='do'][onclick$='()'][onclick*='Eventsearch']

    此句意为:包含属性onclick的值以do开头、以()结尾、含Eventsearch子串的button

    ②通过ele1,ele2可以“或”方式获取多个元素,如何以“或”方式进行多个属性的模糊匹配?如在①中,想以“或”方式匹配多个属性语句?

    ③通过元素文本定位元素:此路不通!Content selectors were deprecated! No more content selectors since CSS3. :contains() was dropped.

    ④通过子元素找父元素:目前似乎还不支持!有一个CSS伪类 :has() 支持这个功能,但还处于草案阶段。

    4. 实践验证

    验证XpathCSS元素定位语句,可使用浏览器的开发者工具辅助:

    在开发者工具的Elements中按Ctrl + F,在搜索框中输入Xpath或CSS语句;

    在开发者工具的Console中使用 $x()和$()$x()传入Xpath语句,$()传入CSS语句,注意,元素定位(或称查找、选择器)语句需要使用单引号或双引号包围

  • 相关阅读:
    MVP福利利用Azure虚拟机玩Windows Server 2012
    负载均衡的基本算法
    RavenDB:基于Windows/.NET平台的NoSQL数据库
    使用Autofac在ASP.NET Web API上实现依赖注入
    Mono 3 的默认Gc是Sgen
    MSDN 杂志 Windows 8 特刊
    AggSharp Agg的.NET 移植
    使用谷歌翻译/微软翻译迅速使你的博客支持多国语言
    Service Bus for Windows server
    用Xwt构建跨平台应用程序[转载]
  • 原文地址:https://www.cnblogs.com/yuhuang/p/12036509.html
Copyright © 2011-2022 走看看