Bra*_*des 5 javascript python selenium
Selenium有一个方便的机制,可以在一次快速往返中相当有效地从DOM中提取数十个或数百个元素:
buttons = driver.find_elements_by_css_selector('button')
Run Code Online (Sandbox Code Playgroud)
结果buttons可以是几十个或几百个元素的列表而没有任何问题.
但是如果你想使用is_displayed()(或者像Java那样调用它isElementDisplayed)来过滤元素,那么事情就会慢慢爬行,因为对方法的每次调用都需要往返浏览器.即使在我最快的开发机器上,每个这样的调用大约需要0.1秒,这意味着100个元素的后续过滤需要10秒(!):
[b.is_displayed() for b in buttons]
Run Code Online (Sandbox Code Playgroud)
如果您想查找具有特定文本的按钮,则会出现同样的问题,因为.text事实上每次查找属性都会调用一个属性,并将其自己的往返返回到浏览器:
[('Subscribe' in b.text) for b in buttons]
Run Code Online (Sandbox Code Playgroud)
这使得编写强大的Selenium测试变得很困难,这些测试注意到关于DOM真正面向用户的两件事:元素是否可见,以及它包含哪些文本.虽然完全远离可见性和文本内容(例如,对于唯一ID或类或文档位置的组合)的转动会使我们的测试运行得更快,但它会在我们的Selenium测试和它正在寻找的按钮之间创建一个不可见的链接,而是让我们的测试关注用户体验以及用户可以在屏幕上看到和阅读的内容.
我的问题:
在初始获取元素期间,有没有办法在浏览器上应用is_displayed()或text测试元素?
或者有没有办法进行批量is_displayed()调用,询问大量元素而不只是一个?
或者从Firefox测试到Firefox下的Selenium的0.1s往返时间完全不合理,并且对其他人来说运行速度更快,这就是为什么这些常见操作的明显批处理版本不存在的原因?
我原以为我可以转向execute_script()从Python 运行(Java名称:),executeScript()并从我的JavaScript代码内部以某种方式执行Selenium的逻辑,这个逻辑背后是"这个元素可见"的复杂概念.遗憾的是,executeScript()似乎没有让脚本访问Selenium本身认为必不可少的任何util函数,因此要访问is-visible函数,我们必须将jQuery或随机Selenium代码片段拉入缺少它们的页面中,干扰测试的整个概念:它只是为了运行我们的测试而在不改变其JS配置文件的情况下测试页面.
谢谢你的任何想法!令我感到惊讶的是,Selenium期望呼叫者executeScript()能够重建这样的功能is_displayed(),正如代码所示,这是Selenium的一个主要特征,看起来需要做很多工作才能获得正确的,并且需要从所有可能的代码,以避免重新发明这样一个重要的轮子.
根据我在查看seleniumpython 绑定源代码后的理解,没有选项可以批量发送命令,例如isElementDisplayed。execute()方法负责通过 JSON Wire Protocol 传输命令,一次仅处理一个命令。
仅供参考,这里是w3c webdriver 规范中的底层isDisplayed()算法。而且,我认为,这就是 chrome webdriver 本身已经实现的。
作为解决方法并依赖此解决方案,我们可以执行 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)
Run Code Online (Sandbox Code Playgroud)
请注意,它只不过是一种解决方法,因为严格来说,它甚至与 webdriver 确定可见性的真正功能相距甚远。
谈到检查text按钮元素的值,除了采用类似的execute_script()方法之外,一种可能的解决方法是使用 XPath 表达式并验证文本:
buttons = driver.find_elements_by_xpath('//button[contains(., "some text")]')
Run Code Online (Sandbox Code Playgroud)