javascript - Selenium 如何批量处理多个 isElementDisplayed 调用?

标签 javascript python selenium

Selenium 有一个方便的机制,可以相当有效地从 DOM 中拉出数十个或数百个元素,并在一次快速往返中:

buttons = driver.find_elements_by_css_selector('button')

结果 buttons 可以是几十个或数百个元素的列表,没有任何问题。

但如果您想使用 is_displayed()(或 Java 调用它,isElementDisplayed)来过滤元素,事情就会变得很慢,因为对该方法的每次调用都涉及往返浏览器。即使在我最快的开发机器上,每次这样的调用也需要大约 0.1 秒,这意味着以下跨越 100 个元素的过滤器需要 10 秒(!):

[b.is_displayed() for b in buttons]

如果你想查找带有特定文本的按钮,也会出现同样的问题,因为每次查找 .text 属性实际上都会调用一个属性,它自己往返于浏览器:

[('Subscribe' in b.text) for b in buttons]

这使得编写健壮的 Selenium 测试变得困难,这些测试要注意 DOM 真正面向用户的两件事:元素是否可见,以及它包含什么文本。虽然完全远离可见性和文本内容——比如,转向唯一 ID 或类组合或文档位置——会使我们的测试运行得更快,但它会在我们的 Selenium 测试和它正在寻找的按钮之间创建一个不可见的链接,而不是让我们的测试关注用户体验以及用户可以在屏幕上看到和阅读的内容。

我的问题:

  • 在初始获取元素期间,是否有任何方法可以对浏览器上的元素应用 is_displayed()text 测试?

  • 或者是否有某种方法可以进行批处理 is_displayed() 调用,询问大量元素而不是一个元素?

  • 或者从 Python 测试到 Firefox 下的 Selenium 的 0.1 秒往返时间是完全不合理的,它对其他人来说运行得更快,这就是为什么不存在这些常见操作的明显批处理版本的原因?

我原以为我可以转向从 Python(Java 名称:executeScript())运行 execute_script(),然后从我的 JavaScript 代码内部以某种方式执行 Selenium 的逻辑这背后隐藏着“这个元素是否可见”的复杂想法。不幸的是,executeScript() 似乎没有让脚本访问 Selenium 本身认为必不可少的任何 util 函数,因此要访问可见函数,我们必须拉取 jQuery 或随机Selenium 代码片段进入原本缺少它们的页面,干扰了测试的整个概念:它按原样测试页面而不更改其 JS 配置文件只是为了运行我们的测试。

感谢您的任何想法!我很惊讶 Selenium 期望 executeScript() 的调用者能够重建像 is_displayed() 这样的功能,从代码中可以看出,这是 Selenium 的一个主要特性看起来需要做很多工作才能正确,并且人们希望从所有可能的代码中访问,以避免重新发明如此重要的轮子。

最佳答案

根据我在查看 selenium python 绑定(bind)源代码后的理解,没有选项可以批量发送命令,如 isElementDisplayedexecute()方法,负责通过 JSON Wire Protocol 传输命令,一次只处理一个命令。

仅供引用,这里是 underlying isDisplayed() algorithm来自 w3c webdriver 规范。而且,我认为,this is what chrome webdriver itself has implemented .

作为解决方法并依赖 this solution ,我们可以执行javascript(未测试):

script = """
function isHidden(el) {
    var style = window.getComputedStyle(el);
    return (style.display === 'none')
}

var result = [];
for (var i = 0; i < arguments.length; i++) {
    result.push(isHidden(arguments[i]));
}
return result;
"""

driver.execute_script(script, *buttons)

请注意,它不过是一种解决方法,因为严格来说,它甚至不接近 webdriver 确定可见性的真正方式。

关于检查按钮元素的 text 值,除了采用类似的 execute_script() 方法外,一种可能的解决方法是使用 XPath 表达式和验证文本:

buttons = driver.find_elements_by_xpath('//button[contains(., "some text")]')

关于javascript - Selenium 如何批量处理多个 isElementDisplayed 调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29221463/

相关文章:

python - 导入错误: DLL load failed: %1 is not a valid Win32 application

javascript - 未定义不是一个函数,Google Geolocation

python - 使用 Python 删除文件中以 octothorpe 开头的行?

javascript - 如何在谷歌街景中保存 "zoom"图像

Python OpenCV - 检测手

selenium - 为功能性 Plone 测试用例记录 Selenium 测试

java - Python/Selenium - 无法获取标签的 HREF 值

java - docker-compose selenium-grid、maven、java。用于设置功能的空 VM 池

javascript - 如何使用 javascript 添加可搜索下拉菜单

javascript - jQuery:检测浏览器是否在 append() 之后完成渲染