为Selenium Webdriver 测试编写可靠定位器
来源:互联网 发布:淘宝店铺故事 编辑:程序博客网 时间:2024/05/23 07:24
原文地址:https://blog.mozilla.org/webqa/2013/09/26/writing-reliable-locators-for-selenium-and-webdriver-tests/
假如你来这里是要寻找一个完美的,牢不可破的定位器,那我恐怕要告诉你,世界上没有完美的定位器。HTML更改和定位器不兼容是编写 UI 自动化测试所面临的现实。只要您的web应用程序在演进,比如说随着开发团队尝试新的设计、简化HTML和修复错误,这时候你不得不更新你的定位器。维护定位器必然成为测试维护成本的一部分。
然而,好消息是,好的和糟糕的定位器之间是有区别的。这意味着如果能设计好你的定位器,你就可以降低维护成本,这样你就可以把时间集中在更重要的工作上,而不是调试错误的结果(由于locator的原因导致的错误----笔者加)
另一方面,一次失败的定位是个好事情,所以不要害怕。信任“NoSuchElementException”远比断言失败好,因为这通常提醒你的软件该进行回归测试了。
在本指南中,我假设你已经知道了如何编写定位器,并且熟悉CSS和XPath定位器的构造和语法。从这里开始,我们将探究在编写Selenium测试时,一个好的定位器和一个坏的定位器的区别。
IDs 是国王
ID 是最安全的定位选项,应该始终是你的首选。按照W3C的标准,一个元素的id值在页面中是独一无二的,这意味着你永远不会遇到一个问题,即找到多个匹配定位器的元素。
ID 也是独立于树外的元素类型和位置,因此如果开发人员移动了元素或者更改了其类型,WebDriver 仍然可以找到它。
ID 经常用于Web页面的JavaScript中(事实上,大多数开发并不是同情测试人员定位元素困难才给元素加上ID的,而是他们自己需要用到才会加),因此开发人员会避免更改元素的ID,因为这将导致他们更改自己的JavaScript。不管怎样,这对我们测试人员来说太棒了。
假如你身边恰巧遇到“灵活”的开发,甚至一只眼放在app 源代码上(一半的精力),你可以尝试着在周五晚上给他买一杯啤酒,尝试和他们的妹妹约会,或者就是直白的乞求,以期望他们能往代码里加入更多的ID。当然大多数情况下,这都是不切合实际的或者不可行的,所以我们需要使用CSS 或者 Xpath 定位器。
CSS 和 XPath 定位器
CSS和XPath 定位器在概念上非常相似,所以我们把它们放在一起讨论。
这些类型的定位器组合了标签名、后代元素、CSS类或元素属性,是的匹配模式严格或宽松。严格是说,小的HTML变化都会使其失效,或者它可能会匹配多个HTML元素。
当编写CSS 或 XPath 定位器时,我们需要在严格和松散之间找到平衡点。使其既能够尽可能久的适应HTML的变化;当应用程序出现错误时,也能足够严格的反应出来。
找到一个锚点元素
使用CSS 或 XPath 定位器的一个好方法是,首先找到一个不太可能改变的元素,使其作为你的定位器锚点。这个锚点可能有个ID,或者是个稳定的位置,这不是你需要定位的元素但时一个可靠的搜索位置。你的锚点元素可以在HTML树的当前元素(目标元素)之上或之下,但大多数情况选择目标元素上面的元素作为锚点。
<div id=”main-section”> <p>Introduction</p> <ul> <li> Option 1</li> </ul></div>在本例中,我们想要定位<li>元素没有ID 或 一个CSS 类标记它,因此很难定位。尤其是还有可能在HTML中有多个列表。div 有个id=“main-section” 可以选为寻找<li>的锚点元素,这样就缩小了定位器正在搜索的HTML(从锚点往下找,不用找正个HTML了)
何时使用“索引”定位器,如 nth-child() and [x]
nth-child(), first-child, [1] 和这些索引类型的定位器只能应用于列表对象。这种情况,测试应该明确知道想要从列表中选择的项目对应哪个索引,例如可以验证一下搜索结果的第一项来验证一下(index[0],不知道list有几个元素,那就打印下第一个元素)。使用一个索引类型的定位器来定位一个不是索引位置的元素,当这个元素的顺序发生改变的时候,可能会引起问题,因此应该避免这种情况。
<menu> <button>Option 1</button> <button>Option 2</button> <button>Option 3</button></menu>
假如不管列表项如何排序,你都只想要与第一个菜单项进行交互时,那么 //menu/button[1] 是一个合适的定位器。如果不是(大多数情况下,我们是想选择列表中的某一项,比如这里的Option 1),而如果button的顺序改变成下面这样,而你还通过 //menu/button[1] 进行定位的时候,就会定位到Option 3,就会导致测试失败。
<menu> <button>Option 3</button> <button>Option 2</button> <button>Option 1</button></menu>这是一个合理的失败?还是需要你重新编写定位器。
根据您测试的目标,非索引定位器,//menu/*[text()=’Option 1’] 可能更合适。这时候<menu>是理想的锚点元素。
CSS 类名称经常透露他们的用途
前端设计人员实际上也是人,他们经常会给CSS 类名称来表示他们的目的。
我们应该利用这一点,选择依赖功能而不是样式的定位器,因为样式通常是会改变的。
<footer class="form-footer buttons"> <div class="column-1"> <a class="alt button cancel" href="#">Cancel</a> </div> <div class="column-2"> <a class="alt button ok" href="#">Accept</a> </div></footer>在上面这个示例中,忽略class column-1和column-2 比较好。他们指的是布局,因此当开发决定调整设计(调整布局)的时候,他们可能会受到变化影响。如果我们能直接对目标按钮(Accept和Cancel按钮)进行操作会更加可靠。虽然button ok 在页面上可能不止一个,看起来像个松散的定位器。但是你可以将页脚作为锚点元素,在这个例子中“,从下往上”定位button ok 是一个好的定位器。
发现未来的脆弱性(易变性)
通过观察HTML,你可以发现潜在未来脆弱性。在离开前面的例子时,我故意留下了超过3个定位器以外的问题。比如说<a> 是一个tag name,<a>后面跟的文本内容,在HTML中,看起来开发人员已经把 text label 改成ok,并且tag改成了button。结果导致class,text content,tag name都匹配不到了。
<footer class="form-footer buttons"> <div class="column-1"> <a class="alt button cancel" href="#">Cancel</a> </div> <div class="column-ok"> <button class="alt ok">ok</button> </div></footer>如果开发团队优柔寡断或尝试使用UX和性能改进,这些也可能会变。我们接下来使用松散的定位器,这将容忍HTML中的一些变化。接下来让我们在松散定位器上犯错,嘿嘿。
直接派生(通过父节点找子节点)
CSS example: div > div > ul > li > span
Xpath example: //div/div/ul/li/span
直接派生类是指HTML 元素的父子关系。在第一个示例中,<li>是<url>的子元素。
在上面的示例中,使用长链的话可能会帮助你找到一个没有class或者id的元素,但从长远来看,他肯定是不可靠的。在没有id或类的情况下,大段的内容是经常动态变化的。而且可能经常移动或在HTML中变换位置。它只需要在链条中找到一个元素然后顺着找下来。
如果你不得不使用直接派生类的定位器,那么尝试在每个定位器中最多使用一个。
根据你的目标去调整
<section id=”snippet”> <div>Blurb</div></section>
只使用你需要的定位器。少即是多! 如果您只是捕获文本,那么使用“# snippet div”这样的定位器是没有必要的。WebDriver将返回定位器# snippet和' #snippet > div的相同文本内容,但是如果div元素被更改为< p >或< span >,则后者将会失效。
定位元素的属性
定位属性和通过CSS类定位非常类似,属性可以是唯一的,但有的时候也会在许多项中重复使用,你必须视情况而定到底什么时候用他。
一般来说,最好避免使用属性,只关注id、tag和css类,但在HTML 5 中,数据属性是稳定的属性,因为它们与web应用程序的功能紧密结合在一起。
tag name、link text, name 的定位策略
这些定位策略只是通过属性或文本字符串查找的快捷方式(Xpath:text())。使用这些规则的规则也适用于标签名称、链接文本和名称。
综上所述:当您在编写一个定位器时,首先查找一个ID,然后使用ID(作为锚定元素)的下一个最近的元素。从那里,看下派生和元素属性,以缩小到要定位的元素。
确切地理解定位器的用途——它仅仅是在站点中导航还是断言元素的顺序?如果单元移动或测试失败,定位器是否能够处理?
定位器的用途将决定你需要在定位器中使用的技术有多严格、多宽松。
祝您好运,并明智地为您节省未来的测试维护和假的负面争论!
- 为Selenium Webdriver 测试编写可靠定位器
- Selenium Webdriver 编写UI自动化测试脚本
- selenium使用testNG测试框架编写webdriver脚本_05
- 自动化测试--selenium-webDriver
- 为selenium配置webdriver
- 为selenium配置webdriver
- 自动化测试selenium webdriver启动
- Selenium自动测试工具-WebDriver
- selenium-不同类型的定位器
- Selenium-webdriver—如何定位测试元素
- Selenium Webdriver Python 测试环境搭建
- 使用NUnit来执行Selenium WebDriver测试
- 自动化测试工具 Selenium WebDriver 入门教程
- selenium webdriver junit自动化测试架构
- Selenium WebDriver 自动化测试截图问题
- 执行 Selenium WebDriver 测试脚本抛出 StaleElementReferenceException
- selenium与webdriver测试弹出窗口
- 自动化测试工具 Selenium WebDriver 入门教程
- javaSE_8系列博客——重要的基础Java类——Exceptions(异常处理机制)--4--总结
- Android开发之Hybrid开发
- spring集成kafka实现producer和consumer
- js原型的通俗理解
- 利用Powershell每天自动设置提取Win10的windows聚焦图片(Spotlight)作为桌面壁纸的方法
- 为Selenium Webdriver 测试编写可靠定位器
- GMCM2017-前景目标提取
- SAP 凭证更改日志查询
- python列表小知识
- 诗歌八 弟子规(弟子规,圣人训)
- [bzoj3208]3208: 花神的秒题计划Ⅰ记忆化搜索+暴力
- Android Studio SVN代码冲突的解决(四)
- C中调用C++函数与C++中调用C函数
- (1)俄罗斯套娃_最大上升子序列