之前已经讲过了 Selenium 操作 Select 实现的下拉列表:Selenium2学习-010-WebUI自动化实战实例-008-Selenium 操作下拉列表实例-Select,但是在实际的日常网页开发中,实现下拉列表的方法、样式、特效有 N 多种,但是无论实现的方法有多少不同,其都会遵循一定的规律,在此我就不再赘述了(有兴趣的小主,可以找有经验的前段请教一下)。同时,此类实现的下拉列表在使用 Selenium 进行定位时,往往不尽如人意,定位比较繁琐。
此文仅以 淘宝网账户注册时选择手机号码所属区域的下拉列表操作为原型,进行 WebUI 自动化中 Selenium 通过 JavascriptExecutor 执行 JavaScript 进行下拉列表操作的实战源码讲解演示,敬请各位小主参阅,希望能对您在日常的 WebUI 自动化脚本编写有一定的启发和帮助。若有不足或错误之处,敬请大神指正,不胜感激!
淘宝网账户注册网页链接:http://reg.taobao.com/member/reg/fill_mobile.htm,页面如下所示:
通过 Chrome 打开网页链接后,点击手机号码所在地下拉列表,随便选一个地区,然后按 F12 查看源码,可以非常容易的定位到下拉列表显示的元素,如下图所示:
同时也可比较容易的找到下拉列表可选项存储的位置(不知道这个 ID 会不会变),如下图所示:
此时获取可选列表数组的 js 脚本为:document.getElementById(‘ks-component3714‘).children[0],若想选择索引为 20 的手机号码地区,则脚本为:document.getElementById(‘ks-component3729‘).children[0].children[20].click(),选择不同地区仅需修改 children[20] 中的索引值即可(注意索引不能超出边界,否则会报错)。OK,编写脚本并执行。
此时悲剧了,用例执行失败,脚本报出如下错误信息:
org.openqa.selenium.WebDriverException: unknown error: Cannot read property ‘children‘ of null (Session info: chrome=41.0.2272.118) |
由提示信息可知,js 脚本获取元素后元素无 children 属性,查看源码(OMG,好大一个坑啊!此时居然没有 id=‘ks-component3714‘ 的元素,即没有下拉选项列表)可知,初始打开页面,手机归属地列表不显示,需要点击一下手机号码所在地区的下拉列表框触发相应的事件,才会出现下拉列表项。通过页面源码及实际操作可知,操作红框中的任意区域,均可触发相应事件,因而编写 js 脚本触发事件(弹出手机号码归属地下拉列表),js 脚本为:document.getElementsByClassName(‘code‘)[0].click(),在自动化脚本选择手机号码归属地的前面添加上述代码,运行 WebUI 自动化脚本,结果如下(OY,成功了):
PASSED: testDroplist02
=============================================== =============================================== |
后续又运行了几次,突然间发现又自动化脚本又报错了,信息如下:
FAILED: testDroplist02 org.openqa.selenium.WebDriverException: unknown error: Cannot read property ‘children‘ of null (Session info: chrome=41.0.2272.118) (Driver info: chromedriver=2.9.248315,platform=Windows NT 6.1 SP1 x86_64) (WARNING: The server did not provide any stacktrace information) Command duration or timeout: 10 milliseconds Build info: version: ‘2.44.0‘, revision: ‘76d78cf‘, time: ‘2014-10-23 20:02:37‘ |
郁闷,为何之前好好的,奈何现在又崩掉了呢?首先可以肯定的是脚本逻辑是没有问题的,那么问题出在哪儿呢?页面源码。查之,列表项的父级 ID 居然变了,将注册页面的 URL 换不同的浏览器多刷新几次,发现父级元素 ID: ks-component3714 后四位有时会变化,不固定(不得不敬佩一下淘宝的攻城狮们,代码写的不错啊,55555)
ZTMDDT,怎么办呢?必须兼容此种问题,怎么兼容呢,DTA!!!
解决思路:通过 JavaScript 脚本的查找 父级、子级、兄弟 元素定位手机号码归属地可选项列表。
追根溯源走起,查源代码,通过分析此部分的源码,发现 class=‘code‘ 仅为手机号码归属地所用,当第一次打开页面时,执行 js 脚本 document.getElementsByClassName(‘code‘) 的结果为当前已选择的手机号码归属地的 code 码(此码不可用于定位手机号码归属地可选项列表,因其为显示所用);当触发了列表事件,显示出可选项列表项时,再次执行 js 脚本,获取到了所有的手机号码归属地的编码列表,如下图所示(第一个为当前已选显示的手机号码归属地):
因不确定手机号码归属地地区编码数组的长度,因而取上图中的第二个(也就是列表项的第一个)为起点,此时 js 脚本为 : document.getElementsByClassName(‘code‘)[1],然后通过获取其父级,进而获取全部的手机号码归属地的子集,最终的手机号码归属地子集脚本为:document.getElementsByClassName(‘code‘)[1].parentNode.parentNode,最终选择手机号码归属地的 js 脚本为:document.getElementsByClassName(‘code‘)[1].parentNode.parentNode.children[18].click()。再次优化 WebUI 自动化脚本,将上述脚本替换原来的脚本,执行自动化脚本,查看自动化脚本执行结果,perfect。
最后奉上此文的 WebUI 自动化脚本源代码,敬请各位小主参阅。若有不足或者错误之处,敬请大神指正,不胜感激!
1 package main.aaron.demo.droplist; 2 3 import main.aaron.sele.core.TestCase; 4 5 import org.testng.annotations.Test; 6 7 /** 8 * Selenium 操作下拉列表实例-div+{js|jquery} 9 * 10 * @author Aaron.ffp 11 * @version V1.0.0: autoSeleniumDemo main.aaron.demo.droplist Droplist02.java, 2015-6-17 00:39:17 Exp $ 12 */ 13 public class Droplist02 extends TestCase{ 14 // 获取淘宝网账户注册的 URL 路径 15 private final String baseUrl = "http://reg.taobao.com/member/reg/fill_mobile.htm"; 16 17 // 手机号码归属地下拉列表 18 private String jscript_onclick = ""; 19 20 // 手机号码归属地选项列表-未兼容列表项 ID 变化的情况 21 private String jscript_items = ""; 22 23 // // 手机号码归属地选项列表-兼容列表项 ID 变化的情况 24 private String jscript_itemsPerfect = ""; 25 26 /** 27 * Selenium 操作下拉列表实例-div+{js|jquery} --- 以淘宝网用户注册时选择手机号码归属地为实例 28 * 29 * @author Aaron.ffp 30 * @version V1.0.0: autoSeleniumDemo main.aaron.demo.droplist Droplist02.java testDroplist02, 2015-6-17 00:42:29 Exp $ 31 * 32 */ 33 @Test 34 public void testDroplist02(){ 35 this.jscript_onclick = "document.getElementsByClassName(‘code‘)[0].click()"; 36 this.jscript_items = "document.getElementById(‘ks-component3712‘).children[0].children[19].click()"; 37 this.jscript_itemsPerfect = "document.getElementsByClassName(‘code‘)[1].parentNode.parentNode.children[18].click()"; 38 39 this.webdriver.get(this.baseUrl); 40 41 this.execJavascript(this.jscript_onclick); 42 43 // this.execJavascript(this.jscript_items); 44 45 this.execJavascript(this.jscript_itemsPerfect); 46 } 47 }
Selenium 操作下拉列表实例-div+{js|jquery} --- 以淘宝网用户注册时选择手机号码归属地为实例
PS:各位小主们,在实际的日常自动化脚本编写过程中,若是有兴趣,可以此为联系,对选择手机号码归属地的 js 进行封装,将其归属地名称或者编码作为参数传入,进而更好地控制脚本,同时也使脚本模块化,更加有利于自动化脚本的编写。
至此,WebUI 自动化功能测试脚本第 012 篇-Selenium 操作下拉列表实例-div+{js|jquery} 顺利完结,希望此文能够给初学 Selenium 的您一份参考。
最后,非常感谢亲的驻足,希望此文能对亲有所帮助。热烈欢迎亲一起探讨,共同进步。非常感谢! ^_^