【问题标题】:Selenium 2.0b3 IE WebDriver, Click not firingSelenium 2.0b3 IE WebDriver,点击不触发
【发布时间】:2011-07-31 07:04:58
【问题描述】:

在使用IE9的IE驱动时,有时Click方法只会选择一个按钮,它不会做Click()的动作。请注意,这只是偶尔发生,所以我认为问题不是代码。在 Firefox4 中使用 Firefox 驱动程序没有问题。我也遇到了偶尔也找不到元素的问题,但只是在 IE 中,而不是在 Firefox 中。

if (Driver.FindElement(By.Name("username")) == null) {
    //sometimes gets here in IE, never gets here in Firefox
}
Driver.FindElement(By.Name("username")).SendKeys(username);
Driver.FindElement(By.Name("surname")).SendKeys(surname);
Driver.FindElement(By.Name("firstname")).SendKeys(firstname);
string url = Driver.Url;
Driver.FindElement(By.Name("cmd")).Click();
if (Driver.Url == url) {
    //if the page didnt change, click the link again
    Driver.FindElement(By.Name("cmd")).Click();
}

我见过类似的问题 (http://stackoverflow.com/questions/4737205/selenium-webdriver-ie-button-issue),但我没有动态生成的 id。

【问题讨论】:

    标签: internet-explorer-9 webdriver selenium-webdriver


    【解决方案1】:

    经过一番搜索后,我发现了两件事似乎对可重复测试有所帮助:

    首先我添加了 5 秒的 ImplicitlyWait。不确定这是否适用于所有 FindElement 函数,但我已经停止获取大部分 NoSuchElementException。

    OpenQA.Selenium.IE.InternetExplorerDriver driver = new OpenQA.Selenium.IE.InternetExplorerDriver();
    driver.Manage().Timeouts().ImplicitlyWait(new TimeSpan(0, 0, 0, 5, 0));
    //driver.Manage().Speed = Speed.Medium;
    

    其次,我遇到了注销功能问题,并将代码更改为:

    public LoginPageObject Logout() {
        Driver.FindElement(By.LinkText("Logout")).Click();
    
        OpenQA.Selenium.Support.UI.IWait<IWebDriver> wait = new OpenQA.Selenium.Support.UI.WebDriverWait(Driver, TimeSpan.FromSeconds(5));
        IWebElement element = wait.Until(driver => driver.FindElement(By.Name("username")));
    
        LoginPageObject lpage = new LoginPageObject(Driver);
        return lpage;
    }
    

    显式等待似乎可以处理 ImplicitlyWait 没有捕获的内容(我认为是因为重定向)。

    http://code.google.com/p/selenium/source/browse/trunk/support/src/csharp/webdriver-support/UI/WebDriverWait.cs?r=10855

    【讨论】:

      【解决方案2】:

      当我尝试使用.Click() 单击链接时,我在 Internet Explorer 8 上发现了同样的情况——即使我可以看到 Selenium 在链接上单击。根据我的经验,如果浏览器没有焦点,那么初始点击将不起作用。

      解决方法是在尝试单击链接之前将.Click() 发送到页面上的另一个元素,以便浏览器获得焦点,例如它是父母:

      Driver.FindElement(By.Id("Logout")).FindElement(By.XPath("..")).Click();
      Driver.FindElement(By.Id("Logout")).Click();
      

      【讨论】:

      • 我很欣赏这个简单的解决方案,以及原因。这有助于我找出问题的最佳解决方案。
      • 我遇到了一个问题,我无法单击我选择的元素的父级。单击同一元素两次有效,但我担心如果窗口已经获得焦点,它可能会导致不需要的行为。对所选解决方案的这种细微更改对我有用:(在 C# 中)driver.FindElement(By.TagName("body")).Click();
      • 还要检查你的 IE 的缩放系数。重要的是 zomm 因子始终设置为 100%!
      • @Naishy:你用什么语言点击使用WebDriver?是Java吗?还是什么?
      • @RiponAlWasim:我一直在使用 C#。
      【解决方案3】:

      遇到同样的问题,点击在我的 IE 中不起作用。我找到了一种解决方法,我在其中执行 Driver.FindElement(By.Name("...")).sendKeys("\n") 来执行单击(基本上我只需按按钮上的 enter)。不是很干净,但在问题解决之前它可以工作!

      【讨论】:

        【解决方案4】:

        我基于在我的项目中引用 Selenium WebDriver 2.15.0 并使用 Selenium WebDriver Server 2.16.0 重构了我的解决方案,并且我做了以下观察:

        • 使用FirefoxDriver 时,点击事件确实正确触发
        • RemoteWebDriver 用于DesiredCapabilities.Firefox 时,某些控件的点击事件不会正确触发
        • RemoteWebDriver 用于DesiredCapabilities.HtmlUnitDesiredCapabilities.HtmlUnitWithJavaScript 时,点击事件确实正确触发
        • InternetExplorerDriverRemoteWebDriverDesiredCapabilities.InternetExplorer(实际上是同一件事)仍然给我带来不一致的结果,我发现很难确定。

        我对前三点的解决方案是创建我自己的扩展 RemoteWebDriverRemoteWebElement 的类,以便我可以在继续引用 IRemoteWebDriverIWebElement 的测试代码中隐藏我的自定义行为。

        我有以下我当前的“调整”,但如果您使用这些自定义类,您将能够根据您的需要调整您的驱动程序和 Web 元素行为,而无需更改您的测试代码。

        public class MyRemoteWebDriver : RemoteWebDriver
        {
            //Constructors...
        
            protected override RemoteWebElement CreateElement(string elementId)
            {
                return new MyWebElement(this, elementId);
            }
        }
        
        public class MyWebElement : RemoteWebElement, IWebElement
        {
            //Constructor...
        
            void IWebElement.Click()
            {
                if (Settings.Default.WebDriver.StartsWith("HtmlUnit"))
                {
                    Click();
                    return;
                }
        
                if (TagName == "a")
                {
                    SendKeys("\n");
                    Thread.Sleep(100);
                    return;
                }
        
                if (TagName == "input")
                {
                    switch (GetAttribute("type"))
                    {
                        case "submit":
                        case "image":
                            Submit();
                            return;
                        case "checkbox":
                        case "radio":
                            //Send the 'spacebar' keystroke
                            SendKeys(" ");
                            return;
                    }
                }
        
                //If no special conditions are detected, just run the normal click
                Click();
            }
        }
        

        【讨论】:

        • (TagName == "input") 并不涵盖所有情况 - 还有<button> tag。您可能还想检查case "button",因为&lt;input&gt;/&lt;button&gt; 可能有自定义脚本逻辑。
        • 另外,if(...HtmlUnit...) 函数为每个元素发送Click(),而在其他情况下它不会回退到Click()
        【解决方案5】:

        我在 2.0rc2、IE8、Java 中也遇到过这种情况。我在实现一个可以发送多次点击的解决方案时遇到的问题是,有时它确实有效。在这些情况下,单击我的对象两次不会让我的其余测试继续进行。在我们的控件上发送“Enter”键也不起作用。

        对此有类似的问题logged,但我的对象不一定靠近“视点”。任何更多建议将不胜感激。

        【讨论】:

          【解决方案6】:

          尝试将Internet 选项-> 安全-> 启用保护模式 设置为所有区域的设置相同,请参阅http://www.mail-archive.com/watir-general@googlegroups.com/msg13482.html。这来自 Watir googlegroup,但在我的 Selenium 2 测试中,IE 按钮点击似乎在应用此功能后效果更好。

          【讨论】:

          • 您可以通过功能做到这一点,但它仍然无法始终如一地工作。
          【解决方案7】:

          我发现 IE 驱动程序有问题,并且相同版本的代码在具有相同 IE 版本的不同机器上表现不同。

          为了在每个动作之前保持一致,我会执行以下操作。

             driver.SwitchTo().Window(driver.CurrentWindowHandle);//Force Focus
          

          对我来说,这使得 IE 驱动程序的行为更加符合预期。

          【讨论】:

          • 很高兴知道,但我认为每次需要焦点时调用 SwitchTo() 有点贵。我认为有“更便宜”的方式来强制集中注意力。
          • 昂贵与否这远远优于作为公认答案的廉价黑客。
          • 这对我来说并不成功。
          • Java 版本:driver.switchTo().window(driver.getWindowHandle());// Force Focus
          【解决方案8】:

          以上解决方案都不适合我。这成功了:

          Java

          element.sendKeys(org.openqa.selenium.Keys.CONTROL);
          element.click();
          

          时髦

          element << org.openqa.selenium.Keys.CONTROL
          element.click()
          

          盖布

          或者,如果您使用的是Geb,还有一个更更好的解决方案,完全不引人注目:

          (用IE7和Geb 0.7.0测试)

          abstract class BaseSpec extends geb.spock.GebSpec
          {
              static
              {
                  def oldClick = geb.navigator.NonEmptyNavigator.metaClass.getMetaMethod("click")
                  def metaclass = new geb.navigator.AttributeAccessingMetaClass(new ExpandoMetaClass(geb.navigator.NonEmptyNavigator))
          
                  // Wrap the original click method
                  metaclass.click = {->
                      delegate << org.openqa.selenium.Keys.CONTROL
                      oldClick.invoke(delegate)
                  }
          
                  metaclass.initialize()
          
                  geb.navigator.NonEmptyNavigator.metaClass = metaclass
              }
          }
          
          class ClickSpec extends BaseSpec
          {
              def "verify click"()
              {
                  given:
                  to HomePage
          
                  expect:
                  waitFor { at HomePage }
          
                  when:
                  dialog.dismiss()
                  // Call the wrapped .click() method normally
                  $('#someLink').click()
          
                  then:
                  waitFor { at SomePage }
              }
          }
          
          class HomePage extends geb.Page
          {
              static url = "index.html"
              static at = { title == "Home - Example.com" }
              static content = {
                  dialog { module DialogModule }
              }
          }
          
          class SomePage extends geb.Page { ... }
          class DialogModule extends geb.Module { def dismiss() { ... } }
          

          在我的例子中,在 IE7 中点击似乎会在关闭动画模式覆盖之前失败(我们使用的是jQuery Tools Overlay Modal Dialog)。上面的Geb方法解决了这个问题。

          【讨论】:

          • 在 C# 中,这对我来说适用于 IE 驱动程序(但不适用于 chrome 等其他驱动程序): Element.SendKeys(Keys.CONTROL); Element.Click();
          • 您能详细说明为什么要发送控制权吗?这不会在新窗口中打开每个点击的链接吗?
          • 上面的代码模拟了目标元素上的按键press(按键down后跟按键up)。在调用oldClick 时,模拟的 Ctrl 键已经被释放,因此链接不会在新的选项卡/窗口中打开。
          • 请注意,我的回答是基于 Emmanuel 的解决方案:向目标元素发送按键事件似乎足以使其获得焦点。我选择了Ctrl 键,因为它不会触发任何默认浏览器行为,而且任何 JavaScript 事件处理程序都不太可能只查找该键。
          • 适用于 java 和 IE。你能解释一下指令 element.sendKeys(org.openqa.selenium.Keys.CONTROL); 的作用吗?做什么?
          【解决方案9】:

          将焦点集中在元素上的更好方法是使用 Javascript。当您的元素使用 id 属性标记时,此方法有效。如果不是,请让开发人员进行更改。

          使用您需要的任何定位器/属性来查找元素。检索到元素后,检查它是否包含 ID 属性。如果是,则执行以下代码,将焦点强制到元素:

          JavascriptExecutor executor = (JavascriptExecutor) webDriver();
          executor.executeScript("document.getElementById('" + element.GetAttribute("id") + "').focus()");
          

          使用这个,几乎所有点击丢失的问题都在使用 InternetExplorerDriver 时得到解决。

          【讨论】:

            【解决方案10】:

            我使用的是 IE 版本:9 面临同样的问题。以下在我的情况下有效

            element.sendKeys(Keys.ENTER);
            element.click();
            

            【讨论】:

              【解决方案11】:

              绝对没有其他事情对我有用。 有些 InternetExplorerDriver click() 对我有用,有些则没有。 然后我发现我在the documentation中漏掉了一行:浏览器的缩放级别必须设置为100%。

              我确信所有其他答案都涉及缩放级别已经为 100% 的情况,但它确实解决了我的情况。所以请先检查一下。

              【讨论】:

                【解决方案12】:

                我通过 .click() 解决了下一个问题。我使用 JS 和 executeScript(JS, WebElement el) 而不是 .click()。
                示例:

                protected void clickForIE(WebElement element){  
                        ((JavascriptExecutor)wd).executeScript("var tmp = arguments[0];
                          tmp.click()", element);  
                    }
                

                但是使用这种方法后,我们应该等待页面加载。这就是我使用下一个方法的原因:

                protected synchronized void pageWaitLoad() {  
                        String str = null;
                        try {
                            str = (String)((JavascriptExecutor)wd).executeScript("return document.readyState");
                        }
                        catch (Exception e) {
                // it's need when JS isn't worked
                            pageWaitLoad();
                            return;
                        }
                        System.out.println("ttt " + str);
                        while(!str.equals("complete")){
                            try {
                                Thread.currentThread().sleep(2000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            str = (String)((JavascriptExecutor)wd).executeScript("return document.readyState");
                        }
                    }
                

                您必须在每次 clickForIE() 之后调用 pageWaitLoad()。

                【讨论】:

                  【解决方案13】:

                  我的解决方案是:

                  Selenium WebDriver 2.29.0 (JAVA),通过 FF16 和 IE9 测试

                  在制作 findElement 之前,我做了一个最大化浏览器屏幕。它工作正常。

                  public void maximeBrowser() {
                          Toolkit toolkit = Toolkit.getDefaultToolkit();
                          Dimension screenResolution = new Dimension((int)toolkit.getScreenSize().getWidth(), (int)toolkit.getScreenSize().getHeight());
                  
                          //Maximize the browser
                          logger.info("Maximizing the browser : getWidth ["+screenResolution.getWidth()+"] - getHeight ["+screenResolution.getHeight()+"]");
                          getDriver().manage().window().maximize();
                      }
                  

                  【讨论】:

                    【解决方案14】:

                    另一个:

                    v2.29.0

                    网络驱动程序: * 火狐 18 支持。 * IEDriver 支持“requireWindowFocus”所需的功能。什么时候 使用此事件和本机事件,IE 驱动程序将需要焦点和 用户交互将使用 SendInput() 来模拟用户 互动。请注意,这意味着您不得使用 在测试运行时运行 IE 的机器。

                    【讨论】:

                      【解决方案15】:

                      作为解决方法,我在每次单击之前使用了带有空字符串的 SendKey:

                      element.SendKeys("");
                      element.Click();
                      

                      【讨论】:

                        【解决方案16】:

                        PHPUnit + facebook / php-webdriver 有时函数 click() 不检查复选框元素。

                        我的解决办法是:

                        $Element = $WebDriver->findElement(
                            WebDriverBy::id('checkbox_id')
                        );
                        
                        if(false === $Element->isSelected())
                        {
                            $Element->sendKeys(WebDriverKeys::SPACE);
                        }
                        

                        【讨论】:

                          【解决方案17】:

                          简答:
                          如果您在 触摸屏 显示器(例如 Windows 8 触摸笔记本电脑)上打开浏览器窗口在 IE11 中运行自动化 Selenium 测试,请尝试在 中打开浏览器窗口运行测试非触摸屏
                          原始的 .click() 方法应该可以在没有所有代码变通方法的情况下正常工作。

                          答案背景:
                          我与我们 QA 团队的一名测试人员一起调查了一个类似的问题。在尝试了此处和selenium webdriver IE button issue 的大部分代码解决方案后,我们最终发现问题仅发生在测试人员的 Windows 8 笔记本电脑触摸屏上的 IE(我们的版本 11)中。
                          使用在外部戴尔显示器上运行的 IE 窗口运行 Selenium 测试可以让测试每次都运行良好,即使只使用标准的 .click() 调用也是如此。
                          我们在 Magnific Popup (http://dimsemenov.com/plugins/magnific-popup/) 对话框中的按钮单击事件上也失败了。

                          我的假设:IE11(不确定其他版本)如何处理触摸事件与触摸屏上的鼠标单击事件之间的转换存在问题。

                          【讨论】:

                            【解决方案18】:

                            WebdriverJS

                            IE 中,当您尝试执行 click() 操作时,URL 在状态栏上一直闪烁。这意味着驱动程序正在关注元素并尝试执行 click() 操作。为了完成它的 click() 动作,我在每次点击动作前后都使用了 sleep() 方法。

                            试试这个例子。

                            var webdriver = require('..'), By = webdriver.By, until = webdriver.until;
                            var driver = new webdriver.Builder().usingServer().withCapabilities({'browserName': 'ie' }).build();
                            
                            driver.get('http://www.google.com')
                            .then(function(){
                                driver.manage().window().maximize();
                                driver.manage().timeouts().implicitlyWait(1000 * 3);
                                driver.findElement(By.name('q')).sendKeys('webdriver');
                                driver.findElement(By.name('btnG')).then(function(button){
                                button.click();
                                });
                            })
                            .then(function(){
                                driver.findElement(By.css('div[class="gb_Zb"] a[title="Google Apps"]')).then(function(apps){
                                    apps.click();       
                                    driver.findElements(By.css('a[class="gb_O"]')).then(function(appsList){
                                    console.log("apps : "+appsList.length);
                                    for(var i = 0; i < appsList.length; i++){
                                    console.log('applications : '+i);
                                    if(i == 5) {
                                    var element = appsList[i];
                                    driver.sleep(1000 * 5);
                                    driver.executeScript("var tmp = arguments[0]; tmp.click()", element);
                                    driver.sleep(1000 * 5);
                                    } } })  
                                })
                            })
                            .then(null, function(err) {
                              console.error("An error was thrown! By Promise... " + err);
                            });
                            driver.quit();
                            

                            要执行点击,我们可以使用其中任何一个,在 IE 上测试过

                            element.click(); 
                            driver.actions().click(element).perform();
                            driver.executeScript("var tmp = arguments[0]; tmp.click()", element);
                            

                            【讨论】:

                              猜你喜欢
                              • 2017-03-19
                              • 2018-03-14
                              • 2017-06-07
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 2013-02-06
                              相关资源
                              最近更新 更多