当我们利用Selenium对web UI进行测试的时候,locator是即为重要的元素,如何准确有效地确定页面中需要测试的元素的locator对web应用程序测试极其重要。但因为selenium支持多种形式的locator,如xpath、CSS、DOM、name、id、link等,所以找locator也就多种多样。比如如果我们知道网页源码结构的话,就可以直接写出相应的locator。但是毕竟现在的网页往往是动态的,而且查看源码费时费力,所以这种方法不是很可取。好在有不少工具能够协助我们实现这一需求。
1. 利用Selenium IDE
我们可以通过firefox添加插件Selenium IDE并开启。当点击红色的录制按钮后,我们对网页进行操作后,该工具会录制所有的行为并转化为selenium命令,当然也就包含有了locator。
方法优点:简单、方便
方法不足:对于一些复杂点的行为可能会漏掉,因此也就无法捕获相应的locator;此外locator是自动获取的,可能不是很直观,另外无法得到统一样式的locator。
2. 利用Firebug
同样firefox的插件中可以添加firebug。在Tools->Web Developer->Firebug中打开Firebug,于是能够看到页面的下半部分有显示Firebug窗口,可以查看HTML,CSS等。因为了解的粗浅,所以只能说说知道的几点简单功能。
如果我们需要查看页面某个元素的locator,可以鼠标右击,选择Inspect Element with Firebug, 于是就到了元素对应的html源码位置。这样我们根据这部分源码来写locator。
但是,往往对于一些element如button等,右击后没有反应时,我们可以考虑选择它们旁边的元素进行,到源码后再通过查找其兄弟元素源码或者上一层来找到相应源码。这里主要根据是当我们鼠标放在以某tag为根节点的源码的上时,上面的页面对应的界面元素会有相应标记。
方法缺点:写出的locator可能并不是页面的唯一,这样selenium运行就难以识别
3. 利用XPather
同样Firefox添加插件XPather,打开后,在页面中右击时会显示Show in XPather,于是就得到元素对应的完整的xpath路径。但是往往从根节点开始的xpath路径太长,而且如果页面稍微有变化就导致locator不可重用。好在我们可以用//来从任何一个节点开始匹配所需元素的节点。输入相应的xpath路径后点击确认后xpather会匹配所打开的页面中所有满足条件的元素信息。这样就可以根据输入的xpath匹配出来的结果不断尝试以得到能够唯一定位相应element的locator。
但是XPather所显示的路径及其简单,而且不带属性,所以要找到这样的唯一的locator很难。于是我们可以根据Firebug来得到element的其他信息,如对应的属性及其值、父节点、子节点等。通过不断的改写xpath并放入测试指导最终找到目标。
XPath语法
XPath语法遵循W3标准,具体参考:http://www.w3school.com.cn/xpath/xpath_syntax.asp
下面主要展示一些常用的写法:
//div
//input[@id='username'] 括号里面 @属性 后面不跟其他表示含有这个属性,如有值则进一步限定
//div[text()='Welcome'] 节点所含的内容,注意如果有空格也要补上
//div[contains(@title,'webpage')] 相应的属性值包含
//div[@id='a' and not contains(@title,'webpage')] 用and来增加约束,not来否定
//div/a 增加一层来找tag为a的
//div[2] 第2个div,//div[last()]
//div/*/a 通过匹配来找
//div/child::a 通过轴来寻找 如果子节点好找而父节点难定位但是我们要找的是父节点,那么我们就可以先找到子节点再借助parent来得到父节点,类似地得到其他 //a[@id='doclink']/parent::div
//div[text()='Compare Versions']//following::a[@title='Close'][1]
//div[text()='Compare Versions']/../../../../../../..//a[@title='Close']
轴的种类及意义参考:http://www.w3school.com.cn/xpath/xpath_axes.asp
如果利用locator找到的匹配节点不只一个,而我们需要得到其中的任何一个节点,该怎么办呢?xpath能够通过括号()来规定运算顺序,因此我们可以写出如下locator:
(//div[contains(@class,'x1bm p_AFEdit')])[1]//a[text()='Add Content']
可是发现我们用selenium模拟时候并没有反应,原来是需要在前面加上xpath,所以可以识别的locator是
xpath=(//div[contains(@class,'x1bm p_AFEdit')])[1]//a[text()='Add Content']