web-UI自动化必会技能—xpath轴,了解一下?
本来以为不会再更新UI自动化相关的东西了,不过最近群里的朋友在搞UI,提出了许多问题,我看了下,大多还是页面元素定位类的问题,那今天就再讲点。
一、先了解xpath
说到元素定位,大家应该都知道常见的几种定位方式:
- find_element_by_name()
- find_element_by_id()
- find_element_by_css_selector()
- find_element_by_xpath()
在定位中,一般情况下,是奔着怎么简单怎么来就好。比如元素带有id的话,那直接根据id来定位。
但是,实际情况中,你可能通篇都找不到id,比如知乎的首页,wtf?
别慌,我们有xpath,不怕不怕。
我之前实现的一个项目,前端就是使用了vue,逼得我只能用xpath去定位,不过用下来发现xpath非常强大且灵活,学会绝对不亏。
举例,还是知乎的首页图,右上方有个回答问题的元素,我现在要去定位它,用xpath://div[.='回答问题'],够简单吧?
对了,这里提一个小tips:当你调试页面的定位语法时候,只需要按F12打开元素页面,然后Ctrl+F,在底部的输入框里输入定位语法即可。
此外,如果使用xpath定位上述例子中的情况,还可以更方便的参数化封装。
比如,我除了要定位“回答问题”,旁边的“发视频”、“写文章”、“写想法”我后面都会用到,那这样就很简单了。
通常,你只需要把//div[.='回答问题']中的文字调整就好了,这时候你就可以进一步抽象出来,以Python语言为例:
def locate_demo(button_name):
"""
定位按钮元素,传参:按钮名称
"""
driver.find_element_by_xpath("//div[.='{}']".format(button_name))
伪代码供参考,是不是觉得xpath还是挺不错的,但是,还不够。
当你的项目逐步深入的时候,你对于定位的通用性追求也会越来越高,需要尽量的抽取通用的封装以供复用,那么对应的,你可能会遇到越来越复杂的层级定位,这时候xpath轴就要登场了。
二、xpath轴登场
其实也比较简单,你只需要2个步骤即可学会。
第一步:认真看下我贴出来的语法
第二步:练习(─━ _ ─━✧)
语法这些东西都一样,熟能生巧,多练习就行了。
举个实际场景应用的例子,说明下xpath轴的优点:
如图所示,这是一个很常见的系统列表。
需求:我现在需要基于列表页进行一个方法的封装,用于通过传入数据名称,可以勾选数据前的勾选框。
解析:既然是要根据不同的列表数据名称找到前面对于的勾选框,那么就来先定位列表名称,很简单,xpath://div[.='景区DPA跳转测试'],在代码里可以用format去参数化,比如
def locate__checkbox_by_name(name):
driver.find_element_by_xpath("//div[.='{}']".format(name))
现在定位到了名称,那么如何定位前面的勾选框呢?
可以看到,黄色高亮部分是定位到的数据名称。checkbox元素所在的节点位于名称元素的上方。再继续看,checkbox往上找第5个父级节点,与黄色高亮的名称元素的父节点处于兄弟级别,那么这时候我们可以用xpath轴来定位了(语法见上部分的图)。
xpath轴定位:思路很简单,就是先定位到黄色高亮区域的父级节点,再通过父级节点定位到前面的兄弟节点,然后再定位到checkbox元素。也就是:
1. //div[.='景区DPA跳转测试']/parent::td
2. //div[.='景区DPA跳转测试']/parent::td/preceding-sibling::td
3. //div[.='景区DPA跳转测试']/parent::td/preceding-sibling::td//input
所以,最终封装操作的方法定位可以这么写:
def locate__checkbox_by_name(name):
driver.find_element_by_xpath("//div[.='{}']/parent::td/preceding-sibling::td//input".format(name))
是不是很方便?定位的灵活性也大大提高了。
最新文章
- 深入理解this机制系列第二篇——this绑定优先级
- 站在巨人的肩膀上---重新自定义 android- ExpandableListView 收缩类,实现列表的可收缩扩展
- C# 6.0的属性(Property)的语法与初始值
- 微软正开发Office Reader和Office Lens
- A coroutine example: Streaming XML parsing using xml_parser
- MySql MyISAM和InnoDB的区别
- web 前端常用组件【03】Bootstrap Multiselect
- 编写2个接口:InterfaceA和InterfaceB;在接口InterfaceA中有个方法void printCapitalLetter();在接口InterfaceB中有个方法void printLowercaseLetter();然 后写一个类Print实现接口InterfaceA和InterfaceB,最后再在主类E 的main方法中创建Print的对象并赋值,运行方法
- NoCache
- Curses library not found. Please install appropriate package
- 黑盒测试用例设计方法&;理论结合实际 ->; 正交试验法
- Miller-Rabin素性测试(POJ3641)
- AndroidAnnotations框架配置
- CODE[VS]-求和-整数处理-天梯青铜
- ural1439 Battle with You-Know-Who
- app后端设计(10)--数据增量更新
- BZOJ2319 : 黑白棋游戏
- usermod - linux修改用户帐户信息
- CentOS 7.4安装Nginx 1.14.0
- 网页中动态嵌入PDF文件/在线预览PDF内容https://www.cnblogs.com/xgyy/p/6119459.html
热门文章
- Java 通过Jna调用dll路径问题
- Python要点总结,我使用了100个小例子!
- Springboot 在@Configuration注解的勒种 使用@Autowired或者@value注解 读取.yml属性失败
- IPv4地址段、地址掩码、可用地址等常用方法
- Nexus2 上传文件
- 2020-04-06:insert语句在mysql里经历了什么?
- C#LeetCode刷题之#622-设计循环队列​​​​​​​(Design Circular Queue)
- C#LeetCode刷题之#110-平衡二叉树(Balanced Binary Tree)
- 旧 WCF 项目成功迁移到 asp.net core web api
- 正规式转化为DFA