Selenium如何批量许多isElementDisplayed调用? [英] How can Selenium batch many isElementDisplayed calls?

查看:388
本文介绍了Selenium如何批量许多isElementDisplayed调用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Selenium has a convenient mechanism for pulling dozens or hundreds of elements from the DOM fairly efficiently and in a single fast round-trip:

buttons = driver.find_elements_by_css_selector('button')

结果按钮可以是几十个或几百个元素的列表而没有任何问题。

The result buttons can be a list of dozens or hundreds of elements without any problem.

但是如果你想要过滤元素,那么事情就会慢慢爬行使用 is_displayed()(或者当Java调用它时, isElementDisplayed ),因为对方法的每次调用都涉及往返回到浏览器。即使在我最快的开发机器上,每个这样的调用大约需要0.1秒,这意味着100个元素的后续过滤需要10秒(!):

But things slow to a crawl if you want to filter the elements using is_displayed() (or as Java calls it, isElementDisplayed) because every call to the method involves a round-trip back to the browser. Even on my fastest development machine each such call takes about 0.1s, which means that the following filter across 100 elements takes 10 seconds (!):

[b.is_displayed() for b in buttons]

如果你发生同样的问题想要查找具有特定文本的按钮,因为 .text 属性的每次查找实际上都会调用一个属性,并将其自己的往返回到浏览器:

The same problem happens if you want to look for a button with particular text, because each lookup of the .text attribute in fact invokes a property with its own round-trip back to the browser:

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

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

This makes it difficult to write robust Selenium tests which pay attention to the two things that are really user-facing about the DOM: whether an element is visible, and what text it contains. While pivoting entirely away from visibility and text content — say, to unique IDs or combinations of classes or document location — would make our tests run faster, it would be creating an invisible link between our Selenium tests and the button it was looking for, instead of letting our tests keep their eye on the user experience and what users can see and read on the screen.

我的问题:


  • 有没有办法申请 is_displayed()文本在初始获取元素期间对浏览器上的元素进行测试?

  • Is there any way to either apply is_displayed() or a text test to elements over on the browser during the initial fetch of elements?

否则有一些方法可以批处理 is_displayed()调用询问大量元素而不只是一个?

Or else is there some way to do a batch is_displayed() call that asks about lots of elements instead of just one?

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

Or is a 0.1s round-trip time from a Python test to Selenium under Firefox just completely unreasonable and it runs faster for everyone else and that's why obvious batch versions of these common operations do not exist?

我以为我可以转而运行 execute_script() Python(Java名称: executeScript())并且从我的JavaScript代码中以某种方式执行Selenium的逻辑,这个逻辑背后是这个元素可见的复杂概念。不幸的是, executeScript()似乎没有让脚本访问Selenium本身认为必不可少的任何util函数,因此要访问is-visible函数,我们必须将jQuery或随机Selenium代码片段拉入缺少它们的页面中,干扰测试的整个概念:它在不改变其JS配置文件的情况下按原样测试页面,只是为了运行我们的测试。

I had thought that I could just pivot to running execute_script() from Python (Java name: executeScript()) and from inside my JavaScript code somehow execute Selenium's logic that lies behind the complicated idea of "is this element visible". Unfortunately executeScript() does not seem to give scripts access to any of the util functions that Selenium itself finds essential, so to get access to an is-visible function we would have to pull either jQuery or a random Selenium code fragment into pages that otherwise lack them, interfering with the whole concept of a test: that it tests the page as-is without changing its JS profile merely in order to run our test.

感谢您的任何想法!我很惊讶Selenium希望调用者 executeScript()重建能力,如 is_displayed(),作为一个瞥了一眼代码建议,这是Selenium的一个主要特性,看起来需要做很多工作才能得到正确的,并且想要从可能的所有代码中访问,以避免重新发明这样一个重要的轮子。 / p>

Thanks for any ideas! I am rather surprised that Selenium expects callers to executeScript() to be rebuilding capability like is_displayed() that, as a glance at the code suggests, is a major feature of Selenium that looks like it took a lot of work to get correct and that one would want to access from all the code that possibly could, to avoid re-inventing such an important wheel.

推荐答案

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

From what I understand after looking into selenium python bindings source code, there is no option to send commands, like isElementDisplayed, in batches. execute() method, which is responsible for transmitting the command via the JSON Wire Protocol, handles a single command at a time only.

仅供参考,这里是基础 w3c webdriver规范中的isDisplayed()算法。而且,我认为,这就是chrome webdriver本身实现的内容

FYI, here is the underlying isDisplayed() algorithm from the w3c webdriver specification. And, I think, this is what chrome webdriver itself has implemented.

作为一种解决方法并依赖此解决方案,我们可以执行javascript(未经测试):

As a workaround and relying on this solution, we can execute javascript (not tested):

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确实可以确定vis ibility。

Note that it is not more than a workaround since, strictly speaking, it is not even close to what webdriver really does to determine visibility.

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

Speaking about checking the text value of the button elements, one possible workaround, aside from taking a similar execute_script() approach, would be to use an XPath expression and verify the text:

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

这篇关于Selenium如何批量许多isElementDisplayed调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆