zoukankan      html  css  js  c++  java
  • fw: webdriver 那些坑

      http://www.cnblogs.com/huang0925/p/3384596.html

    使用WebDriver遇到的那些坑

     

    在做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,就可以升级到目前的版本。

    4、得到文本框里的文字

      1. assertEquals(selenium.getValue("xpath=//input[@name='WNO']"), "1");

      getValue 方法就是得到文本框里的数值,可不是 getText 方法,用错了可就郁闷了。

      5、判断页面是否存在一个元素

      1. assertTrue(selenium.isElementPresent("xpath=//input[@name='MEICK_000']"));

      一般这个是用来测试当删除一些数据后,页面上有些东西就不会显示的情况。

      6、判断下拉框里选择了哪个选项

      1. assertEquals(selenium.getSelectedIndex("xpath=//SELECT[@name='HATIMING']"), "1");

      这个可以用来判断下拉框显示的选项是否是期望的选项。

      7、如果有 alert 弹出对话框怎么办?

      这个问题弄了挺长时间,可以这样来关闭弹出的对跨框:

      1. if(selenium.isAlertPresent()) {

      2.

      3.    selenium.getAlert();

      4.

      5. }

      其实当调用 selenium.getAlert() 时,就会关闭 alert 弹出的对话框。

      也可以使用 System.out.println(selenium.getAlert()) 来查看对跨框显示的信息。

      在测试的时候,有的人会显示许多alert 来查看运行时的数据,那么我们可以用下面的方式来关闭那些 alert:

      1. while(selenium.isAlertPresent()) {

      2.

      3.    selenium.getAlert();

      4.

      5. }

      8、如何测试一些错误消息的显示?

      1. assertTrue(selenium.getBodyText().indexOf("错误消息")>=0);

      切记: getBodyText 返回的时浏览器页面上的文字,不回包含html 代码的,如果要显示html 代码,用下面这个:

      1. System.out.println(selenium.getHtmlSource());

      以上就是最常用的几个方法了,例如 click, type, getValue 等等。

      还有就是一定要学习 xpath, 其实xpath 也可以有“与、或、非”的操作:

      1. selenium.check("xpath=//input[(@name='KNYKBN')and(@value='Y')]");

      四、其他

      selenium 还有更多的用法,例如弹出页面等等。当面对没见过的测试要求时,我最笨的方法就是按照api文档一个一个找,

  • 相关阅读:
    企业nginx应用实例(功能拆分记录)
    Squid代理服务器的安装与配置
    关于mysql主从架构master宕机后,请求转移问题解决办法
    记一次innobackupex备份恢复数据库过程
    elasticsearch6.6及其插件安装记录(较详细)
    redis一主二从加哨兵
    nginx反向代理proxy_pass的问题
    spring程序打包war,直接通过-jar启动,并指定spring.profiles.active参数控制多环境配置
    Debian下配置防火墙iptables
    内连接和外连接
  • 原文地址:https://www.cnblogs.com/dracula/p/3597508.html
Copyright © 2011-2022 走看看