【问题标题】:Is it possible to ignore JavaScript exceptions when working with WebDriver (HtmlUnit, Ruby bindings)使用 WebDriver(HtmlUnit、Ruby 绑定)时是否可以忽略 JavaScript 异常
【发布时间】:2012-02-03 10:16:59
【问题描述】:

当我加载页面时,HtmlUnit 抛出异常并导致我的测试崩溃

caps = Selenium::WebDriver::Remote::Capabilities.htmlunit(:javascript_enabled => true)
driver = Selenium::WebDriver.for(:remote, :desired_capabilities => caps)
driver.navigate.то url

ReferenceError:“x”未定义。 (net.sourceforge.htmlunit.corejs.javascript.EcmaError)

如果我使用 Firefox 驱动程序,则不会引发异常。

caps = Selenium::WebDriver::Remote::Capabilities.firefox

或者为 HtmlUnit 驱动禁用 JavaScript

caps = Selenium::WebDriver::Remote::Capabilities.htmlunit(:javascript_enabled => false)

我无法更改测试页面上的代码并修复问题,因此我需要忽略它或以任何方式使用 Firefox JavaScript 引擎而不是标准的 HtmlUnit JavaScript 引擎。

不修改测试页代码可以解决我的问题吗?

更新: 尝试将 Capybara + WebKit 作为 Selenium + HtmlUnit 的替代品 - 工作正常,没有错误。但我仍然想在不改变框架的情况下解决问题。

【问题讨论】:

标签: javascript ruby selenium webdriver htmlunit


【解决方案1】:

根据@Vitaly 的回答

    import org.openqa.selenium.htmlunit.HtmlUnitDriver;
    import com.gargoylesoftware.htmlunit.WebClient;
    import java.util.logging.Logger;
    import java.util.logging.Level;
    public class MyHtmlUnitDriver extends HtmlUnitDriver {
        protected void modifyWebClient() {
            /* turn off annoying htmlunit warnings */
            Logger.getLogger("com.gargoylesoftware").setLevel(Level.OFF);
            WebClient newWebClient = getWebClient();
            newWebClient.getOptions().setThrowExceptionOnScriptError(false);
            newWebClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
            newWebClient.getOptions().setPrintContentOnFailingStatusCode(false);
            modifyWebClient(newWebClient);
        }
    }

【讨论】:

    【解决方案2】:

    此方法将永远关闭任何记录器!

    static void setFinalStatic(Field field, Object newValue) throws Exception {
            field.setAccessible(true);
    
            Field modifiersField = Field.class.getDeclaredField("modifiers");
            modifiersField.setAccessible(true);
            modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
    
            field.set(null, newValue);
        }
    
    
    setFinalStatic(com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine.class.getDeclaredField("LOG"), new org.apache.commons.logging.Log() {
    
                });
    

    【讨论】:

      【解决方案3】:

      我能够使用HPUnit_Extensions_Selenium2TestCase v1.4.0 解决它,如下所示:

      class TestBase extends PHPUnit_Extensions_Selenium2TestCase
      {
          public function setUp()
          {
              $this->setHost(<your-host>);
              $this->setPort(<your-port>);
              $this->setDesiredCapabilities(Array("javascriptEnabled"=>"false"));
      

      【讨论】:

        【解决方案4】:

        仅适用于 Java: 在最新版本的WebClient(由HTMLUnitDriver 包装)中,不推荐使用client.setThrowExceptionOnScriptError(false) 方法。如果子类化 HTMLUnitDriver,则需要重写 modifyWebClient 方法:

        public class MyHtmlUnitDriver extends HtmlUnitDriver {
        
        ...
        
         @Override
            protected WebClient modifyWebClient(WebClient client) {
                //currently does nothing, but may be changed in future versions
                WebClient modifiedClient = super.modifyWebClient(client);
        
                modifiedClient.getOptions().setThrowExceptionOnScriptError(false);
                return modifiedClient;
            }
        }
        

        【讨论】:

          【解决方案5】:

          我在 .net 世界中发现了同样的问题。

          我在 c# 中使用反射和扩展方法解决了这个问题:

          public static void SetThrowOnScriptErrors(this HtmlUnitDriver driver, 
                                                    bool throwScriptErrors )
          {
              object webClient =  driver.GetType().InvokeMember("_webClient",
                                              BindingFlags.GetField | 
                                              BindingFlags.NonPublic | 
                                              BindingFlags.Instance, null,
                                              driver, new object[0]);
          
              webClient.GetType().InvokeMember("throwExceptionOnScriptError_",
                                                  BindingFlags.SetField | 
                                                  BindingFlags.NonPublic | 
                                                  BindingFlags.Instance,
                                                  null, webClient, 
                                                  new object[] {throwScriptErrors});
          }
          

          【讨论】:

            【解决方案6】:

            查看source of the HtmlUnitDriver 后,似乎无法自定义您想要更改的行为。解决此问题的最简单方法是修补并重新编译 Selenium 服务器(这可能是也可能不是一个选项)。您需要添加这一行:

            --- HtmlUnitDriver.java 2012-01-05 17:45:22.779579136 +0100
            +++ HtmlUnitDriver.java 2012-01-05 18:14:51.415106195 +0100
            @@ -255,6 +255,7 @@
                 WebClient client = newWebClient(version);
                 client.setHomePage(WebClient.URL_ABOUT_BLANK.toString());
                 client.setThrowExceptionOnFailingStatusCode(false);
            +    client.setThrowExceptionOnScriptError(false);
                 client.setPrintContentOnFailingStatusCode(false);
                 client.setJavaScriptEnabled(enableJavascript);
                 client.setRedirectEnabled(true);
            

            【讨论】:

            • 或者,您可以继承 HtmlUnitDriver 并覆盖受保护的 newWebClient()。
            猜你喜欢
            • 1970-01-01
            • 2014-02-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-10-26
            • 2023-01-30
            相关资源
            最近更新 更多