在StackOverflow上,我看到用户报告说他们无法通过selenium WebDriver“单击”命令单击元素,并且可以通过执行脚本来解决JavaScript单击问题。
Python中的示例:
element = driver.find_element_by_id("myid") driver.execute_script("arguments[0].click();", element)
WebDriverJS /量角器中的示例:
var elm = $("#myid"); browser.executeScript("arguments[0].click();", elm.getWebElement());
问题:
为什么在常规WebDriver单击不起作用时单击“通过JavaScript”有效?这到底是什么时候发生的,这种解决方法(如果有)的缺点是什么?
我个人使用此变通办法时并未完全理解为什么必须这样做以及它可能导致什么问题。
与当前接受的答案所暗示的相反,PhantomJS并没有特定于WebDriver单击和使用JavaScript的区别。
区别
两种方法之间的本质区别是所有浏览器都共有的,可以很简单地解释一下:
WebDriver:当WebDriver进行单击时,它会尽可能地尝试模拟真实用户使用浏览器时发生的情况。假设你有一个元素A,它是一个表示“单击我”的按钮,一个元素B是一个div透明的元素,但具有其尺寸和zIndex设置,使其完全覆盖A。然后告诉WebDriver单击A。WebDriver将模拟点击,使B 首先获得点击。为什么?因为B涵盖了A,并且如果用户尝试单击A,则B将首先获得该事件。A是否最终会获得click事件取决于B如何处理该事件。无论如何,在这种情况下,WebDriver的行为与真实用户尝试单击A时的行为相同。
zIndex
JavaScript:现在,假设你使用JavaScript来做A.click()。这种单击方法不能重现用户尝试单击A时实际发生的情况。JavaScript将click事件直接发送给A,而B将不会获得任何事件。
A.click()
为什么在WebDriver单击不起作用时JavaScript单击有效?
正如我上面提到的,WebDriver会尽可能地模拟真实用户使用浏览器时发生的情况。事实是,DOM可以包含用户无法与之交互的元素,并且WebDriver不允许你单击这些元素。除了我提到的重叠情况之外,这还意味着无法单击不可见元素。我在“堆栈溢出”问题中看到的一个常见情况是有人试图与DOM中已经存在的GUI元素进行交互,但是只有在处理了其他某些元素后才可见。有时在下拉菜单中会发生这种情况:你必须先单击按钮,然后弹出菜单,然后才能选择菜单项。如果有人尝试在菜单可见之前单击菜单项,如果此人随后尝试使用JavaScript进行操作,那么它将起作用,因为事件是直接传递给元素的,而与可见性无关。
什么时候应该使用JavaScript进行点击?
如果你使用Selenium来测试应用程序,那么我对这个问题的回答是“几乎不会”。总的来说,你的Selenium测试应该重现用户对浏览器的操作。以下拉菜单为例:测试应单击首先显示下拉菜单的按钮,然后单击菜单项。如果由于按钮不可见而导致GUI出现问题,或者按钮无法显示菜单项或类似内容,则测试将失败并且你将检测到该错误。如果使用JavaScript单击鼠标,则将无法通过自动测试检测到这些错误。
我说“几乎从不”是因为使用JavaScript可能会有例外。但是,它们应该很少见。
如果你使用Selenium 抓取站点,则尝试重现用户行为并不那么重要。因此,使用JavaScript绕过GUI并不是什么大问题。