8

我创建了另一个问题,我认为这是导致此错误的原因:为什么 Selenium Firefox 驱动程序认为当父级溢出时我的模式不显示:隐藏?

Selenium 2.33.0 版
火狐驱动

导致错误的代码:

        System.Threading.Thread.Sleep(5000);
        var dimentions = driver.Manage().Window.Size;
        var field = driver.FindElement(By.Id("addEmployees-password")); //displayed is true
        field.Click(); //works fine
        var element = driver.FindElement(By.Id(buttonName)); //displayed is false
        element.Click(); //errors out

它试图点击的按钮:

<div id="addEmployees" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="addEmployeesLabel" aria-hidden="true">

    <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
        <h3>Add Employee</h3>
    </div>

    <div class="modal-body">
        <p class="alert alert-info">
            <input name="addEmployees-username" id="addEmployees-username" />
            <input name="addEmployees-password" id="addEmployees-password" type="password" />
            <input name="addEmployees-employee" id="addEmployees-employee" />
        </p>
    </div>

    <div class="modal-footer">
        <button name="addEmployees-add" id="addEmployees-add" type="button" class="btn" data-ng-click="submit()">Add</button>
    </div>

</div>
  • 如果我将调用更改为FindElements然后我得到一个元素,所以页面上没有其他任何内容。
  • 如果我FindElement在按钮之前出现的字段上,比如说addEmployees-employee,那么addEmployees-employeedisplayed
  • 在浏览器本身中,它显示得很好,我需要做的就是实际单击按钮并执行所需的行为,但是 webdriver 拒绝考虑显示的元素

一个字段可以被认为显示而另一个字段不能被认为是如何显示的?

在此处输入图像描述

右下角带有添加按钮的模态,显示所有其他元素 = true

窗口大小为每 1200x645driver.Manage().Window.Size;
元素位置为:每 800x355y 元素尺寸为:每 driver.FindElement(By.Id(buttonName)).Location
51x30 driver.FindElement(By.Id(buttonName)).Size
密码元素位置为:每 552x233y driver.FindElement(By.Id("addEmployees-password")).Size

4

5 回答 5

5

Brian 的回答是正确的:使用显式等待而不是 Thread.Sleep()。Sleep() 通常很脆弱,你会不必要地失去五秒钟,而且它只是自动化测试的一种非常糟糕的做法。(我花了很长时间才知道这一点,所以你并不孤单。)

避免隐式等待。它们通常适用于添加到 DOM 的新项目,而不适用于使模态变为活动状态的过渡。

显式等待有一组很好的 ExpectedConditions(在 Javadox 中有详细说明),可以帮助您解决这些问题。使用与下一个操作所需的状态相匹配的 ExpectedCondition。

另外,请参阅Ian Rose 关于该主题的精彩博文

于 2013-07-15T22:34:31.650 回答
4

Selenium WebDriver 不仅检查当前元素的 opacity != 0、visibility = true、height > 0 和 display != none,而且它还会搜索 DOM 的祖先链以确保没有父元素也匹配这些跳棋。(更新查看所有绑定引用的 JSON 线代码后,SWD 还需要溢出!=隐藏以及 其他 一些 情况 。)

在按照@Brian 的建议重构代码之前,我会做两件事。

  1. 确保“div.modal_footer”元素没有任何理由让 SWD 认为它不可见。

  2. 注入一些 Javascript 以在浏览器中突出显示有问题的元素,这样您就绝对知道您选择了正确的元素。您可以将此要点作为起点。如果按钮以黄色边框突出显示,那么您知道您选择了正确的元素。如果不是,则表示所选元素位于 DOM 中的其他位置。如果是这种情况,您可能没有预期的唯一 ID,这使得 DOM 的操作非常混乱。

如果我不得不猜测,我会说第二个就是你遇到的。这也发生在我身上,开发人员重用了元素 ID,导致争用您应该在哪个元素中找到。

于 2013-07-16T14:42:47.940 回答
1

在聊天中与您讨论后,我认为最好的解决方案(至少目前)是将按钮从您的模态页脚移到它的正文中。

这就是你想要的(现在):

<div class="modal-body">
   <p class="alert alert-info">
      <input name="addEmployees-username" id="addEmployees-username" />
      <input name="addEmployees-password" id="addEmployees-password" type="password" />
      <input name="addEmployees-employee" id="addEmployees-employee" />
      <button name="addEmployees-add" id="addEmployees-add" type="button" class="btn" data-ng-click="submit()">Add</button>
   </p>
</div>

而不是这个:

<div class="modal-body">
   <p class="alert alert-info">
      <input name="addEmployees-username" id="addEmployees-username" />
      <input name="addEmployees-password" id="addEmployees-password" type="password" />
      <input name="addEmployees-employee" id="addEmployees-employee" />
   </p>
</div>

<div class="modal-footer">
   <button name="addEmployees-add" id="addEmployees-add" type="button" class="btn" data-ng-click="submit()">Add</button>
</div>
于 2013-07-11T22:40:14.557 回答
1

我遇到了相同的元素不可见问题,因此无法与之交互。它刚刚得到解决。我更新了我的 selenium 独立服务器。以前的版本是2.33.0,现在是2.35.0

于 2013-10-28T05:23:55.553 回答
0

在我的情况下,该元素已经存在于页面中,但它被禁用了,所以这不起作用(python):

wait.until(lambda driver: driver.find_element_by_id("myBtn"))
driver.find_element_by_id("myBtn").click()

它失败并出现错误:

“Element is not currently visible and so may not be interacted with"

为了解决我的问题,我不得不等待几秒钟(time.sleep(5))直到元素变得可见。

您还可以使用 JavaScript 启用该元素,这是一个 python 示例:

driver.execute_script("document.getElementById('myBtn').disabled='' ")
driver.execute_script("document.getElementById('myBtn').click() ")
于 2015-03-26T08:20:02.433 回答