故事:
在StackOverflow上,我看到用户报告说他们无法通过SeleniumWebDriver“click”命令单击元素,并且可以通过执行脚本通过JavaScript单击来解决这个问题
Python中的示例:
element=driver.通过\u id(“myid”)查找\u元素
驱动程序。执行_脚本(“参数[0]。单击();”,元素)
WebDriverJS/量角器中的示例:
var elm=$(“#myid”);
browser.executeScript(“参数[0]。单击();”,elm.getWebElement());
问题:
为什么当一个普通的WebDriver点击不起作用时,点击“通过JavaScript”却起作用?这究竟是什么时候发生的?这种变通方法的缺点是什么(如果有的话)
我个人使用了此解决方案,但没有完全理解为什么我必须这样做,以及它会导致什么问题。
与目前公认的答案相反,当WebDriver点击和使用JavaScript点击之间的区别出现时,PhantomJS没有什么特别之处
区别
这两种方法之间的本质区别对于所有浏览器都很常见,可以简单地解释为:
-
WebDriver:当WebDriver进行单击时,它会尽可能模拟真实用户使用浏览器时发生的情况。假设您有一个元素a,它是一个显示“单击我”的按钮元素B是一个透明的
div元素,但其尺寸和zIndex设置为完全覆盖a。然后您告诉WebDriver单击a。WebDriver将模拟单击,以便B首先接收单击。为什么?因为B覆盖了A,如果用户试图点击A,那么B会首先得到事件。A是否最终会得到click事件取决于B如何处理该事件。无论如何,在这种情况下,WebDriver的行为与实际用户尝试单击Web应用程序时的行为相同 -
JavaScript:现在,假设您使用JavaScript执行
A。单击()当用户尝试单击A时,这种单击方法不会再现实际发生的情况。JavaScript将单击事件直接发送到A,而B不会获得任何事件
为什么当WebDriver单击不起作用时JavaScript单击起作用
正如我前面提到的,WebDriver将尽可能模拟真实用户使用浏览器时发生的情况。事实上,DOM可以包含用户无法交互的元素,WebDriver不允许您单击这些元素。除了我提到的重叠情况外,这还意味着不能单击不可见的元素。我在堆栈溢出问题中看到的一个常见情况是,有人试图与DOM中已经存在的GUI元素进行交互,但只有在其他元素被操作时才可见。下拉菜单有时会出现这种情况:在选择菜单项之前,您必须首先单击按钮以打开下拉菜单。如果有人试图在菜单可见之前单击该菜单项,WebDriver会犹豫,说该元素无法操作如果此人尝试使用JavaScript执行此操作,则此操作将有效,因为事件将直接传递到元素,而与可见性无关。
什么时候应该使用JavaScript进行单击
如果您使用Selenium对应用程序进行测试,我对这个问题的回答是“几乎永远不会”。总的来说,您的Selenium测试应该再现用户对浏览器的操作。以下拉菜单为例:测试应该首先单击打开下拉菜单的按钮,然后单击菜单项。如果GUI出现问题,因为按钮不可见,或者按钮无法显示菜单项,或者类似的东西,那么测试将失败,您将检测到错误如果使用JavaScript四处点击,则无法通过自动测试检测到这些错误。
我之所以说“几乎永远不会”,是因为可能会有一些例外情况,在这些情况下使用JavaScript是有意义的。不过,它们应该非常罕见
如果您将Selenium用于抓取站点,那么尝试重现用户行为就没有那么重要了。因此,使用JavaScript绕过GUI的问题较少