selenium从零开始到放弃之疑难杂症总结

来源:互联网 发布:刺客信条黑旗优化差 编辑:程序博客网 时间:2024/05/21 19:31

话说最近在做自动化测试项目的时候,遇到一个比较奇葩的问题,比较棘手,刚开始拿到几乎毫无头绪。最后终于在

不断的尝试过程中将其解决。而且该类问题在网上几乎找不到可供参考的完整文章,有人曾经问过类似的问题(htt

p://bbs.csdn.net/topics/390528583),但看答案基本没有靠谱的。所以特总结于此,与各位进行分享。

那么这究竟是个什么样的问题呢?其实是这样,在登录我司内部web测试网站时,输入网址之后,由于是测试服务

器,运维人员在服务器上做了权限验证,所以每次打开新的浏览器实例,系统都会首先要求你输入有效的用户名和密

码进行验证。如果验证不通过,则根本无法进入系统。这个机制非常像我们平时在登陆自家路由器控制台时的验证机

制,必须先输入正确的用户名和密码,否则不让登陆,界面根本就无法显示。如下图所示: 


话说最近在做自动化测试项目的时候,遇到一个比较奇葩的问题,比较棘手,刚开始拿到几乎毫无头绪。最后终于在不断的尝试过程中将其解决。而且该类问题在网上几乎找不到可供参考的完整文章,有人曾经问过类似的问题(http://bbs.csdn.net/topics/390528583),但看答案基本没有靠谱的。所以特总结于此,与各位进行分享。
那么这究竟是个什么样的问题呢?其实是这样,在登录我司内部web测试网站时,输入网址之后,由于是测试服务器,运维人员在服务器上做了权限验证,所以每次打开新的浏览器实例,系统都会首先要求你输入有效的用户名和密码进行验证。如果验证不通过,则根本无法进入系统。这个机制非常像我们平时在登陆自家路由器控制台时的验证机制,必须先输入正确的用户名和密码,否则不让登陆,界面根本就无法显示。如下图所示: 
登陆权限验证

点击“取消”之后,页面是这样的: 


这里写图片描述

有些朋友看到这个界面,可能会觉得很简单,平时见过太多用户名密码验证框了,这个不是很easy吗?呵呵,最开始我见到它的时候也这样想,但随后的操作立马就让我感觉“一脸懵逼”啊。 
 
 
这里写图片描述

这里有什么坑呢?首先第一个坑就是,你会发现这个框、包括这个页面完全没有办法使用“右键”来“查看”对象属性!也就意味着你根本没有办法知道它内部的任何对象属性,也就没有办法用webdriver来对它进行任何操作了。所以,首先可以放弃直接使用webdriver来输入用户名和密码,并点击“确定”按钮的想法。
此路不通,还有别路可走么?由于此界面确实非常简单,webdriver操作不了,那用其他辅助工具能操作吗?我首先想到的是sikuli。sikuli作为一个以图像对比作为基础的测试工具,可以直接解决对象属性拿不到的问题,而且该页面是静态页面,元素并不复杂,所以图片对比也没有什么问题,貌似该办法可行。
基本想好思路后,立马就开始到官网下载sikuli的IDE和webdriver调用时sikuli会用到的相关jar包,配好环境后,就可以开始动手试验了。说到配置sikuli环境,我不得不吐槽两句,太麻烦了,官网自带bug不说,而且目前的版本做得非常烂(根本不像麻省的水准 啊)。都什么年代了还只支持jdk1.6 32位版本(1.7及以上的版本或64位jdk版本均不支持,一个大写的“雷”啊!)待会最后再总结一下sikuli在windows 7 环境中的配置过程。
环境配置好后,在IDE中把selenium工程建好,加入sikuli相关的jar包,就可以开始写脚本了。最开始我写的脚本如下:

package selenium.sikuli.demoimport ...public class LoginPage {    public static void main(String[] args) throws InterruptedException, FindFailed{        System.setProperty("webdriver.firefox.bin", "C:\\Program Files\\Mozilla Firefox\\firefox.exe");        WebDriver driver = new FirefoxDriver();        //打开路由器管理控制台地址        driver.get("http://192.168.1.1");        //sikuli对比时用的图片路径,我是放工程目录下的pic文件夹的        String imgPath = "pic/";        Screen screen = new Screen();        //依次输入用户名、密码,再点击确定按钮,进行登录        screen.type(imgpath + "username.png", "admin");        screen.type(imgpath + "password.png", "admin");        screen.click(imgpath + "login.png");        System.out.println("操作结束");        //driver.quit();    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

好了,吭哧吭哧敲完,点击运行。结果firefox启动后,路由器控制台界面顺利打开,弹出用户名和密码输入框。。。。纳尼????我足足等待了五分钟,用户名和密码一个字母都没有输入进去,准确的说是“毫无动静”,关键还不报错!!!!控制台console中也没有任何信息输出。只有当我手动点击弹出框的取消按钮后,才开始在控制台输出sikuli的运行日志,说明此时sikuli在正常运行。但由于提示框已经被我点击取消按钮并消失了,所以自然就会抛出findfailed这个异常了。这TM简直是哔了dog了!!一股沮丧的心情油然而生,忙活了半天居然不起作用??kao,我不服!再继续想办法。 

这里写图片描述

接下来,仔细分析原因。在确保环境方面没有任何问题之后,开始分析代码。这里有个现象非常奇怪,为什么每次都是一弹出输入框脚本就没有反应了,并且每次都要我手动点击取消按钮后,sikuli运行日志才输出出来表明它在运行呢?在左思右想之后,我终于想到了问题所在。原来这个页面除了根本无法识别对象这个坑之外,还有一个“巨坑”是,这个弹出的输入框是个系统级的标准模态输入框,在你没有输入正确的值的时候,它会完全block住后面的所有操作,也就意味着,在执行完driver.get(“http://192.168.1.1“)之后,webdriver脚本就完全停止下来了,后面的语句根本就没法执行,除非这个模态输入框消失。这也就解释了刚刚说的那个非常奇怪的现象。
原因找到了,接下来就是想解决办法了。要解决这个问题,必须做到两点:

  1. 调用sikuli的线程不能跟webdriver是一个线程,否则一定会被block住
  2. 必须在执行driver.get(“xxxxx”)之前就启动sikuli的线程,否则也难逃被block的命运


问题和解决办法都想到了,其实脚本就相对比较好写了。毫无疑问,这里必须用到多线程了,而且运行sikuli这个线程

必须先于driver.get()方法启动。但由于这样sikuli和webdriver就运行在不同的线程中,所以其实sikuli并不知道driver什

么时候开了页面,所以这里只能先做一下线程等待,具体的等待时间大家可以根据待测页面的实际情况来决定。核心

代码如下:

public class LoginPage {    public static void main(String[] args) throws InterruptedException, FindFailed{        System.setProperty("webdriver.firefox.bin", "C:\\Program Files\\Mozilla Firefox\\firefox.exe");        WebDriver driver = new FirefoxDriver();        //启动sikuli线程        Thread t = new Thread(new Runnable() {            @Override            public void run() {                try {                    Thread.sleep(5000);                } catch (InterruptedException e1) {                    e1.printStackTrace();                }                Screen screen = new Screen();                String imgpath = "pic/";                try {                    screen.type(imgpath + "username.png", "admin" );                    screen.type(imgpath + "password.png", "admin");                    screen.click(imgpath + "login.png");                } catch (FindFailed e) {                    e.printStackTrace();                }            }        });        t.start();        //主线程中继续跑webdriver的业务        driver.get("http://192.168.1.1");    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32


写完之后,点击运行,这个时候再来观察。哈哈,我们想要的值终于被输入到对应的文本框中,并顺利用脚本完成了

登录过程,问题终于解决了。


最后再总结一下,本文中所涉及这个问题,主要有两个“坑”点:

  • 对象根本无法识别。对于对象根本无法识别的问题,一般来说我们都只有借助第三方工具来解决,比如autoit,sikuli都是比较常用的。但要注意的是,如果被测页面过于复杂或是随时变化,那这些辅助工具估计也无济于事。
  • 对于webdriver线程被完全阻塞这种情况,其实我也是第一次遇到,相信大多数人都没有遇到过。那么这种时候,只能用第三方辅助工具进行测试,而且必须用到多线程技术,绕开被block的webdriver线程,单独另起一个线程来执行。


好了,这个问题也算是一个疑难杂症了,好歹化了几个小时时间最终还是顺利解决,希望能对大家有所帮助和启发。


文章最后,再简单记录下sikuli的环境配置过程:(详细过程如果有朋友不太清楚的话,请参考网上其他专门讲述该配

置的文章)


  • 首先下载并安装sikuli的IDE和执行环境安装包(建议在windows环境下安装,mac和linux环境下坑较多)。必须注意的是,安装前必须先按照要求装好1.6版本32位的JAVA JDK或JRE,高于1.6或64位的JDK/JRE都无效,并且参照官网说明打好补丁包。
  • 安装好sikuli的环境后,最好运行下sikuli的IDE验证下是否安装正确。
  • 为了确保eclipse中的其他jar包能够正常运行,建议此时再安装并配置JDK1.7环境(JAVA_HOME改为1.7的,并在eclipse项目中设置java编译器版本为1.7,否则由于1.6太老,有些其他jar包无法兼容,可能导致项目无法运行)。配置为1.7后,应该不会影响之前已经安装好的sikuli,大家可以运行下sikuli的IDE以做验证。
0 0