在做web项目的自动化端到端测试时主要使用的是Selenium WebDriver来驱动浏览器。Selenium WebDriver的优点是支持的语言多,支持的浏览器多。主流的浏览器Chrome、Firefox、IE等都支持,手机上的浏览器Android、IPhone等也支持,甚至还支持PhantomJS(由于PhantomJS跑测试时并不需要渲染元素,所以执行速度快)。

但是我在使用Selenium WebDriver时,遇到了很多坑。这些问题,有的是因为Selenium WebDriver与浏览器不同版本之间兼容性的问题,有的是Selenium WebDriver本身的bug,当然也不乏自己对Selenium WebDriver某些功能理解不透彻。我花时间总结了一下,分享给大家,希望大家以后遇到问题可以避过这些坑,少走弯路。另外也总结了一些使用WebDriver的比较好的实践,也一并分享给大家。

  • WebDriver每次启动一个Firefox的实例时,会生成一个匿名的profile,并不会使用当前Firefox的profile。这点一定要注意。比如如果访问被测试的web服务需要通过代理,你想直接设置Firefox的代理是行不通的,因为WebDriver启动的Firefox实例并不会使用你这个profile,正确的做法是通过FirefoxProfile来设置。
1
2
3
4
5
6
7
8
9
10
11
public WebDriver create() {
FirefoxProfile firefoxProfile = new FirefoxProfile();
firefoxProfile.setPreference("network.proxy.type",1);
firefoxProfile.setPreference("network.proxy.http",yourProxy);
firefoxProfile.setPreference("network.proxy.http_port",yourPort);
firefoxProfile.setPreference("network.proxy.no_proxies_on","");
return new FirefoxDriver(firefoxProfile);
}

通过FirefoProfile也可以设置Firefox其它各种配置。如果要默认给Firefox安装插件的话,可以将插件放置到Firefox安装目录下的默认的plugin文件夹中,这样即使是使用一个全新的profile也可以应用此plugin。

  • 使用WebDriver点击界面上Button元素时,如果当前Button元素被界面上其他元素遮住了,或没出现在界面中(比如Button在页面底部,但是屏幕只能显示页面上半部分),使用默认的WebElement.Click()可能会触发不了Click事件。

修正方案是找到该页面元素后直接发送一条Click的JavaScript指令。

1
((JavascriptExecutor)webDriver).executeScript("arguments[0].click();", webElement);
  • 当进行了一些操作发生页面跳转时,最好加一个Wait方法等待page load完成再进行后续操作。方法是在某个时间段内判断document.readyState是不是complete。
1
2
3
4
5
6
7
8
9
10
11
12
13
    protected Function<WebDriver, Boolean> isPageLoaded() {
return new Function<WebDriver, Boolean>() {
@Override
public Boolean apply(WebDriver driver) {
return ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete");
}
};
}
public void waitForPageLoad() {
WebDriverWait wait = new WebDriverWait(webDriver, 30);
wait.until(isPageLoaded());
}
  • 如果页面有Ajax操作,需要写一个Wait方法等待Ajax操作完成。方式与上一条中的基本相同。比如一个Ajax操作是用于向DropDownList中填充数据,则写一个方法判断该DropDownList中元素是否多余0个。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    private Function<WebDriver, Boolean> haveMoreThanOneOption(final By element) {
return new Function<WebDriver, Boolean>() {
@Override
public Boolean apply(WebDriver driver) {
WebElement webElement = driver.findElement(element);
if (webElement == null) {
return false;
} else {
int size = webElement.findElements(By.tagName("option")).size();
return size >= 1;
}
}
};
}
public void waitForDropDownListLoaded() {
WebDriverWait wait = new WebDriverWait(webDriver, 30);
wait.until(isPageLoaded());
}

以此类推,我们可以判断某个元素是否呈现、某个class是否append成功等一系列方法来判断ajax是否执行完成。

  • 如果网站使用了JQuery的动画效果,我们在运行测试的时候其实可以disable JQuery的animation,一方面可以加快测试的速度,另一方面可以加强测试的稳定性(如果启用了Animation,使用WebDriver驱动浏览器时可能会出现一些无法预料的异常)。
1
((JavascriptExecutor)driver).executeScript("jQuery.fx.off=true");
  • 由于WebDriver要驱动浏览器,所以测试运行的时间比较长,我们可以并行跑测试以节省时间。如果你使用的是maven构建工具,可以配置surefire plugin时,在configruation节点加入以下配置。
1
2
3
<parallel>classes</parallel>
<threadCount>3</threadCount>
<perCoreThreadCount>false</perCoreThreadCount>
  • 当测试fail的时候,如果当前使用的WebDriver实现了TakesScreenshot接口,我们就可以调用相应的方法截下当前浏览器呈现的web页面,这样有利于快速定位出错的原因。
1
2
3
4
5
6
    public void getScreenShot() {
if (webDriver instanceof TakesScreenshot) {
TakesScreenshot screenshotTaker = (TakesScreenshot) webDriver;
File file = screenshotTaker.getScreenshotAs(savePath);
}
}
  • 如果页面弹出了浏览器自带的警告框(使用JavaScript的Alert方法),Selenium WebDriver在点选次警告框时会偶发性失败。具体原因还未查明。解决方案是尽量不使用Alert方法的警告框,而是自己实现模式窗口(比如Jquery UI的模式窗口)来实现警告框效果。这样即保证了测试的稳定性,另外我们自己可以控制警告框的样式,给用户带来更好的体验。

  • 经常更新Selenium的版本。注意经常上Selenium的官网看是否发布了新的版本,新的版本都修复了那些bug,如果包含你遇到的bug,就可以升级到目前的版本。

selenium学习备忘的更多相关文章

  1. Android学习备忘笺01Activity

    01.设置视图 在Android Studio新建的项目中,通过 setContentView(R.layout.activity_main);方法将res/layout/activity_main. ...

  2. leaflet 学习备忘

    leaflet 开源js地图工具.非常好用. leaflet参考:http://leafletjs.com/ 特性: 完全开源,可以基于不同的第三方瓦片生成地图. 基于原始GPS,无需转换 可创建离线 ...

  3. UML学习备忘

    两大类UML图: 行为图(behavior diagrams)和结构图(structure diagrams)     行为图将引导系统分析员分析且理清"系统该做些什么"?系统分析 ...

  4. Git学习备忘

    本文参考廖雪峰写的精彩的git学习文档,大家可以直接去官网看原版,我这里只是便于自己记录梳理 原版地址:http://www.liaoxuefeng.com/wiki/0013739516305929 ...

  5. MVC4 学习备忘

    WebConfig文件里添加数据库链接字符: <add name="MovieDBContext(可以自己取字符串名字)" connectionString="Da ...

  6. 一滴一点vim(学习+备忘)

    普通模式: h j k l 分别是左下上右方式移动: :w 保存修改 :q 推出 :wq 保存修改并退出 :q! 放弃修改强制推出 x 删除光标所在位置字符 i 在光标所以位置插入字符 删除类命令: ...

  7. xml 基础学习备忘

    <?xml version="1.0" encoding="UTF-8"? standalone="yes"> 这里的encod ...

  8. Oracle存储过程学习备忘

    之前的项目使用存储过程很少,但在实际的项目中,存储过程的使用是必不可少的. 存储过程是一组为了完成特定功能的SQL 语句 集,经编译后存储在数据库中:存储过程创建后,一次编译在程序中可以多次调用,对安 ...

  9. jQuery学习备忘

    jQuery对象转换成DOM对象 var #cr = $("#cr"); //jQuery对象 var cr = $cf[0]; //DOM对象 alert(cr.checked) ...

随机推荐

  1. logrotate工具日志切割

    /var/log/zabbix/zabbix_server.log { daily ##每天转储 rotate ##保留60个备份 olddir /usr/local/src ##保存日志的位置 co ...

  2. 利用zookeeper生成唯一id,通用性代码

    在上篇中是写死的,这章就写出通用的 package com.cxy.com.cxy.curator; import java.util.concurrent.ExecutorService; impo ...

  3. nginx FastCGI模块配置

    这个模块允许nginx同FastCGI协同工作,并且控制哪些参数将被安全传递. location / { fastcgi_pass localhost:9000;# 或者http://ip:9000; ...

  4. git学习---去除版本控制

    本地这样去除文件夹 node_modules 的版本关联:执行:git rm -r --cached "node_modules/"提交: git commit -am 'remo ...

  5. poj3111 选取物品(二分+贪心)

    题目传送门 题意就是,n个物品,从中选取k个,要按照那个公式所取的值最大. 思路:最大化平均值的时候首先想到的就是二分, 我们设G(x) 为单位的重量不小于X, 我们的目标就是要找到满足条件的最大的X ...

  6. HDU3555 区间的数里面有49的个数(数位dp)

    题目:区间的数里面有49的个数 分析: dp[pos][0]:长度为pos的数中,不包含49的,前一位不为4的有多少个:dp[pos][1]:长度为pos的数中,不包含49的,前一位为4的有多少个:d ...

  7. poj2001 Shortest Prefixes(字典树)

    Shortest Prefixes Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 21642   Accepted: 926 ...

  8. 用dango框架搭建博客网站

    1.我早先下载了Anaconda35.0.1.但是Anaconda自带的编辑器Spyder我用的不太熟练.所以还是使用Pycharm来编辑代码.我的Pycharm试用期已经到了,所以需要注册码来使用P ...

  9. REQUIRED与REQUIRED_NEW

    出处: https://blog.csdn.net/selfsojourner/article/details/74561745 spring 事务的传播行为中,有两个容易混淆的行为:REQUIRED ...

  10. Google Zxing 生成二维码

    Net Zxing 源码地址 http://zxingnet.codeplex.com/ github 地址 https://github.com/zxing/zxing 新建一个Winform 项目 ...