51Testing软件测试论坛

标题: 为Selenium Webdriver 测试编写可靠定位器 [打印本页]

作者: 子豪_002    时间: 2019-3-22 15:58
标题: 为Selenium Webdriver 测试编写可靠定位器

假如你来这里是要寻找一个完美的,牢不可破的定位器,那我恐怕要告诉你,世界上没有完美的定位器。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树的当前元素(目标元素)之上或之下,但大多数情况选择目标元素上面的元素作为锚点。

  1. <div id=”main-section”>
  2.     <p>Introduction</p>
  3.     <ul>
  4.       <li> Option 1</li>
  5.     </ul>
  6. </div>
复制代码

在本例中,我们想要定位<li>元素没有ID 或 一个CSS 类标记它,因此很难定位。尤其是还有可能在HTML中有多个列表。div 有个id=“main-section” 可以选为寻找<li>的锚点元素,这样就缩小了定位器正在搜索的HTML(从锚点往下找,不用找正个HTML了)



何时使用“索引”定位器,如 nth-child()  and [x]

        nth-child(), first-child, [1] 和这些索引类型的定位器只能应用于列表对象。这种情况,测试应该明确知道想要从列表中选择的项目对应哪个索引,例如可以验证一下搜索结果的第一项来验证一下(index[0],不知道list有几个元素,那就打印下第一个元素)。使用一个索引类型的定位器来定位一个不是索引位置的元素,当这个元素的顺序发生改变的时候,可能会引起问题,因此应该避免这种情况。

  1. <menu>
  2.   <button>Option 1</button>
  3.   <button>Option 2</button>
  4.   <button>Option 3</button>
  5. </menu>
复制代码

假如不管列表项如何排序,你都只想要与第一个菜单项进行交互时,那么 //menu/button[1]  是一个合适的定位器。如果不是(大多数情况下,我们是想选择列表中的某一项,比如这里的Option 1),而如果button的顺序改变成下面这样,而你还通过 //menu/button[1]  进行定位的时候,就会定位到Option 3,就会导致测试失败。

  1. <menu>
  2.   <button>Option 3</button>
  3.   <button>Option 2</button>
  4.   <button>Option 1</button>
  5. </menu>
复制代码

这是一个合理的失败?还是需要你重新编写定位器。


        根据您测试的目标,非索引定位器,//menu/*[text()=’Option 1’]  可能更合适。这时候<menu>是理想的锚点元素。


CSS 类名称经常透露他们的用途

        前端设计人员实际上也是人,他们经常会给CSS 类名称来表示他们的目的。

        我们应该利用这一点,选择依赖功能而不是样式的定位器,因为样式通常是会改变的。

  1. <footer class="form-footer buttons">
  2.   <div class="column-1">
  3.       <a class="alt button cancel" href="#">Cancel</a>
  4.   </div>
  5.   <div class="column-2">
  6.       <a class="alt button ok" href="#">Accept</a>
  7.   </div>
  8. </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都匹配不到了。

  1. <footer class="form-footer buttons">
  2.   <div class="column-1">
  3.       <a class="alt button cancel" href="#">Cancel</a>
  4.   </div>
  5.   <div class="column-ok">
  6.       <button class="alt ok">ok</button>
  7.   </div>
  8. </footer>
复制代码

如果开发团队优柔寡断或尝试使用UX和性能改进,这些也可能会变。我们接下来使用松散的定位器,这将容忍HTML中的一些变化。接下来让我们在松散定位器上犯错,嘿嘿。



直接派生(通过父节点找子节点)

CSS example: div > div > ul > li > span
Xpath example: //div/div/ul/li/span

直接派生类是指HTML 元素的父子关系。在第一个示例中,<li>是<url>的子元素。

在上面的示例中,使用长链的话可能会帮助你找到一个没有class或者id的元素,但从长远来看,他肯定是不可靠的。在没有id或类的情况下,大段的内容是经常动态变化的。而且可能经常移动或在HTML中变换位置。它只需要在链条中找到一个元素然后顺着找下来。

如果你不得不使用直接派生类的定位器,那么尝试在每个定位器中最多使用一个。


根据你的目标去调整

  1. <section id=”snippet”>
  2.     <div>Blurb</div>
  3. </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(作为锚定元素)的下一个最近的元素。从那里,看下派生和元素属性,以缩小到要定位的元素。
确切地理解定位器的用途——它仅仅是在站点中导航还是断言元素的顺序?如果单元移动或测试失败,定位器是否能够处理?
定位器的用途将决定你需要在定位器中使用的技术有多严格、多宽松。
祝您好运,并明智地为您节省未来的测试维护和假的负面争论!







欢迎光临 51Testing软件测试论坛 (http://bbs.51testing.com/) Powered by Discuz! X3.2