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

本文是本人正在准备的《Selenium Webdriver 从零开始到放弃》一文中的一个章节,主要用于收集在测试过程中遇到的各种比较奇葩的问题,分享给大家。一方面自己做个总结,另一方面如果有人遇到同样的问题可以做个参考。本章节的内容会持续更新,其他章节的内容在写完后也会陆续发布在这里,让大家先睹为快,共同学习和提高。

话说最近在做自动化测试项目的时候,遇到一个比较奇葩的问题,比较棘手,刚开始拿到几乎毫无头绪。最后终于在不断的尝试过程中将其解决。而且该类问题在网上几乎找不到可供参考的完整文章,有人曾经问过类似的问题(http://bbs.csdn.net/topics/390528583),但看答案基本没有靠谱的。所以特总结于此,与各位进行分享。

那么这究竟是个什么样的问题呢?其实是这样,在登录我司内部web测试网站时,输入网址之后,由于是测试服务器,运维人员在服务器上做了权限验证,所以每次打开新的浏览器实例,系统都会首先要求你输入有效的用户名和密码进行验证。如果验证不通过,则根本无法进入系统。这个机制非常像我们平时在登陆自家路由器控制台时的验证机制,必须先输入正确的用户名和密码,否则不让登陆,界面根本就无法显示。如下图所示:

![登陆权限验证](https://img-blog.csdn.net/20160827002048367)

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

![这里写图片描述](https://img-blog.csdn.net/20160827014955830)

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

![这里写图片描述](https://img-blog.csdn.net/20160827130531334)

这里有什么坑呢?首先第一个坑就是,你会发现这个框、包括这个页面完全没有办法使用“右键”来“查看”对象属性!也就意味着你根本没有办法知道它内部的任何对象属性,也就没有办法用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.demo
import ...
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();
	}
	
}

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

![这里写图片描述](https://img-blog.csdn.net/20160827130350849)

接下来,仔细分析原因。在确保环境方面没有任何问题之后,开始分析代码。这里有个现象非常奇怪,为什么每次都是一弹出输入框脚本就没有反应了,并且每次都要我手动点击取消按钮后,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");
	}
}

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

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

  • 对象根本无法识别。对于对象根本无法识别的问题,一般来说我们都只有借助第三方工具来解决,比如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以做验证。

欢迎大家关注我的公众号:Python极客栈
selenium从零开始到放弃之疑难杂症总结_第1张图片

你可能感兴趣的:(自动化测试工具)