原文地址: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树的当前元素(目标元素)之上或之下,但大多数情况选择目标元素上面的元素作为锚点。
在本例中,我们想要定位Introduction
- Option 1
何时使用“索引”定位器,如 nth-child() and [x]
nth-child(), first-child, [1] 和这些索引类型的定位器只能应用于列表对象。这种情况,测试应该明确知道想要从列表中选择的项目对应哪个索引,例如可以验证一下搜索结果的第一项来验证一下(index[0],不知道list有几个元素,那就打印下第一个元素)。使用一个索引类型的定位器来定位一个不是索引位置的元素,当这个元素的顺序发生改变的时候,可能会引起问题,因此应该避免这种情况。
假如不管列表项如何排序,你都只想要与第一个菜单项进行交互时,那么 //menu/button[1] 是一个合适的定位器。如果不是(大多数情况下,我们是想选择列表中的某一项,比如这里的Option 1),而如果button的顺序改变成下面这样,而你还通过 //menu/button[1] 进行定位的时候,就会定位到Option 3,就会导致测试失败。
这是一个合理的失败?还是需要你重新编写定位器。根据您测试的目标,非索引定位器,//menu/*[text()=’Option 1’] 可能更合适。这时候