我与硒的webdriver 2.25.0工作多语言的Web应用程序和主要测试页面内容(如阿拉伯语,英语,俄语和等不同的语言)。
对于我的应用程序,它是更好的根据性能和确保它应该是所有的浏览器的支持(即IE 7,8,9,FF,铬等)。
在此先感谢您的建议,居停。
我与硒的webdriver 2.25.0工作多语言的Web应用程序和主要测试页面内容(如阿拉伯语,英语,俄语和等不同的语言)。
对于我的应用程序,它是更好的根据性能和确保它应该是所有的浏览器的支持(即IE 7,8,9,FF,铬等)。
在此先感谢您的建议,居停。
CSS选择器执行远比Xpath的更好,它在硒的社区有据可查。 这里有一些原因,
但也有一些地方,你需要使用XPath,例如,寻找一个父元素或它的文本搜索元素的情况下(我不推荐的更新版本)。
您可以从西门阅读博客在这里 。 他还建议在CSS的Xpath。
如果您正在测试的内容则不要使用依赖于元素的内容选择。 这将是一个维护的噩梦了各个地区。 尝试与开发人员和采用的技术,他们使用的外部化在应用程序中的文本,如字典或资源包等说话这里是我的博客 ,解释得很详细。
由于@parishodak,这里是链接提供的数字证明了CSS性能更好
我要保持不受欢迎的SO硒标签认为XPATH 最好 ,从长远来看CSS。
让我先解决“房间里的大象” - XPath是不是CSS慢。
随着目前CPU电源(读:在过去5年中产生的任何东西),甚至在browserstack / saucelabs虚拟机,以及浏览器的开发(读:在过去5年所有流行的)是很难的情况。 浏览器的引擎开发,的XPath的支持是均一的,即是出来的照片(希望对我们大多数人)。 在对方的回答这个比较被引用的所有的地方,但它是非常情境 - 有多少正在运行 - 或者不关心 - 对IE8?
如果是有区别的,它是在一毫秒的一小部分 。
然而,大多数高级框架添加的开销至少为1ms以上原始硒呼叫反正(包装,处理程序存储状态等); robotframework - - 我个人选择的武器至少2ms的,我很乐意牺牲东西它提供了更多的补充。 从AWS美国东部-1的网络往返于BrowserStack的集线器通常是11毫秒 。
因此,与远程浏览器是否有XPath和CSS之间的差异,它是由一切黯然失色。
有没有那么多的市民比较(我真的看到了一个引用),所以 - 这里有一个粗略单的情况下,虚拟和简单。 目标 - BrowserStack的着陆页,并且它的“注册”按钮; 在HTML的截图:
下面是测试代码(蟒蛇):
from selenium import webdriver
import timeit
if __name__ == '__main__':
xpath_locator = '//div[@class="button-section col-xs-12 row"]'
css_locator = 'div.button-section.col-xs-12.row'
repetitions = 1000
driver = webdriver.Chrome()
driver.get('https://www.browserstack.com/')
css_time = timeit.timeit("driver.find_element_by_css_selector(css_locator)",
number=repetitions, globals=globals())
xpath_time = timeit.timeit('driver.find_element_by_xpath(xpath_locator)',
number=repetitions, globals=globals())
driver.quit()
print("css total time {} repeats: {:.2f}s, per find: {:.2f}ms".
format(repetitions, css_time, (css_time/repetitions)*1000))
print("xpath total time for {} repeats: {:.2f}s, per find: {:.2f}ms".
format(repetitions, xpath_time, (xpath_time/repetitions)*1000))
对于那些谁不熟悉Python -它打开网页,发现该元素-用CSS定位,然后再与XPath的; 查找操作重复1000次。 输出是在用于1000个重复秒的总时间,以及用于以毫秒为单位一个发现平均时间。
定位器是 - 为的xpath - “具有此确切类值的div元素,在DOM某处”; CSS的相似 - “与此类div元素,在DOM地方”。 故意选择不超过调谐; 也,类选择器被引为CSS“第二最快后的ID”。
环境 - 铬v66.0.3359.139,chromedriver v2.38,CPU:ULV核心M-5Y10通常在1.5GHz的运行(是的, “文字处理” 一项,甚至没有一个正规的i7兽)。
下面是输出:
CSS总时间1000次重复:8.84s,每发现:8.84ms
XPath的总时间为1000次重复:8.52s,每发现:8.52ms
显然,每发现时机已经很接近; 的差为0 0.32 毫秒 。 不要跳跃 - 的XPath是更快的 - 有时候是,有时候它的CSS。
让我们尝试与另一组定位器的,更复杂的一个微小的位 - (至少对我常用的方法,当它的一部分带有特殊意义的元素的课后去),其子属性:
xpath_locator = '//div[contains(@class, "button-section")]'
css_locator = 'div[class~=button-section]'
这两个定位器再次语义上是相同的 - “寻找有国际级的div元素属性这串”。 下面是结果:
CSS总时间1000次重复:8.60s,每发现:8.60ms
XPath的总时间为1000次重复:8.75s,每发现:8.75ms
0.15ms的差异。
随着更复杂的DOM,结果是相同的; 我没有任何可公开获得的网址,在手举一个例子,但再次看到了XPath和CSS类似的结果。
作为一个练习-如做了同样的测试链接博客中的评论/其他的答案-在测试页面是公开的,因此是测试代码 。
他们正在做两件事情中的代码 - 单击列通过它来进行排序,然后让这些值,并检查UI排序是正确的。 我就砍了 - 刚拿到定位器,毕竟这是根检验,对不对?
相同的代码如上述,这些变化在:
URL是现在http://the-internet.herokuapp.com/tables
; 有2次测试。
“通过ID和类查找元素” - - 为第一个定位器包括:
css_locator = '#table2 tbody .dues'
xpath_locator = "//table[@id='table2']//tr/td[contains(@class,'dues')]"
结果:
CSS总时间1000次重复:8.24s,每发现:8.24ms
XPath的总时间为1000次重复:8.45s,每发现:8.45ms
0.2毫秒的差异。
在“查找元素通过遍历”:
css_locator = '#table1 tbody tr td:nth-of-type(4)'
xpath_locator = "//table[@id='table1']//tr/td[4]"
结果:
CSS总时间1000次重复:9.29s,每发现:9.29ms
XPath的总时间为1000次重复:8.79s,每发现:8.79ms
这一次,它是0.5毫秒(在倒车时,XPath的横空出世“快”在这里)。
所以,出XPath和CSS,这两个选择的性能? 答案很简单-选择通过ID定位 。
长话短说,如果一个元素的ID是唯一的(因为它应该根据规格来定),它的价值起着DOM的浏览器的内部表示了重要的作用,因此通常是最快的。
随着表现出来的画面,为什么我觉得XPath是更好? 简单 - 多功能性和动力。
XPath是一种用于处理XML文档开发的语言; 正因为如此,它允许更强大的结构比CSS。
例如,在树中的每个方向导航 - 找到一个元素,然后去其祖父母和搜索具有某些特性它的孩子。 它允许嵌入的布尔条件 - COND1和不(COND2与否(COND3和COND4)); 嵌入式选择 - “发现有这些孩子具有这些属性一个div,然后根据它导航”。 它允许基于节点的值搜索 - 然而一旦这种做法是皱起了眉头,它不进来尤其是在严重结构化文档方便的(没有明确的属性来踩,如动态ID和班级)。
CSS中的步进肯定是更容易 - 一个可以在几分钟内开始的事项的书面选择; 但一对夫妇使用的几天后,动力和可能性的XPath迅速克服CSS。
而纯粹是主观的 - 一个复杂的CSS是更难比一个复杂的XPath表达式来阅读。
最后,再次非常主观的 - 来选择哪一个? 恕我直言,有没有正确或错误的选择 - 它们是同一问题的不同解决方案,不管是更适合这个工作应该挑选。 作为XPath的风扇我不会羞于在我的项目中使用两者的混合 - 赫克,有时是要快得多,只是抛出一个CSS一个,如果我知道它会做的工作就好了。
VS 的XPath cssSelector之间的争论将继续作为硒社区最主观的辩论之一。 我们已经知道,到目前为止哪些可以概括为:
戴夫Haeffner进行了测试上具有两个HTML数据表页 ,一个表而没有有益的属性(ID和类 ),和其他与它们写入。 我分析了试验程序和本实验在讨论细节结局为什么我要永远使用cssSelector选择,而不是XPath的自动化测试? 。 虽然这个实验证明,每一个定位战略是跨浏览器相当于合理,但并未充分画的全貌我们。 戴夫Haeffner在其他讨论的CSS比。 X路径,在显微镜下所提到的,在一个终端到终端的测试有在玩沙司启动了很多其他变量, 浏览器启动 ,并且潜伏期和测试的应用程序。 从实验的不幸外卖可能是一个驱动程序可能会比其他(如IE 火狐 VS)更快,而事实上,这是不是在所有的情况。 为了获得性能上的差异是cssSelector和XPath之间什么是真正的味道,我们需要深入挖掘。 我们这样做,但是使用一种性能基准测试工具将数据从本地机器上运行的一切。 我们还专注于一个特定的硒行动,而不是整个试运行,并运行的东西无数次。 我分析了具体的测试程序和本实验在讨论细节成果cssSelector VS XPath的硒 。 但测试仍下落不明即更多的浏览器覆盖一个方面(例如,IE浏览器9和10)和测试针对更大和更深的页面。
戴夫Haeffner在另外一个讨论的CSS比。 X路径,在显微镜下(第2部分)中提到,为了确保所需要的基准覆盖在我们需要考虑最好的方式,演示了一个大而深的页面的例子 。
为了证明这一点具体的例子,在Windows XP虚拟机设置和红宝石(1.9.3)安装。 所有可用的浏览器和硒它们的等效浏览器的驱动程序也安装。 为标杆,Ruby的标准库benchmark
使用。
require_relative 'base'
require 'benchmark'
class LargeDOM < Base
LOCATORS = {
nested_sibling_traversal: {
css: "div#siblings > div:nth-of-type(1) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3) > div:nth-of-type(3)",
xpath: "//div[@id='siblings']/div[1]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]/div[3]"
},
nested_sibling_traversal_by_class: {
css: "div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1 > div.item-1",
xpath: "//div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]/div[contains(@class, 'item-1')]"
},
table_header_id_and_class: {
css: "table#large-table thead .column-50",
xpath: "//table[@id='large-table']//thead//*[@class='column-50']"
},
table_header_id_class_and_direct_desc: {
css: "table#large-table > thead .column-50",
xpath: "//table[@id='large-table']/thead//*[@class='column-50']"
},
table_header_traversing: {
css: "table#large-table thead tr th:nth-of-type(50)",
xpath: "//table[@id='large-table']//thead//tr//th[50]"
},
table_header_traversing_and_direct_desc: {
css: "table#large-table > thead > tr > th:nth-of-type(50)",
xpath: "//table[@id='large-table']/thead/tr/th[50]"
},
table_cell_id_and_class: {
css: "table#large-table tbody .column-50",
xpath: "//table[@id='large-table']//tbody//*[@class='column-50']"
},
table_cell_id_class_and_direct_desc: {
css: "table#large-table > tbody .column-50",
xpath: "//table[@id='large-table']/tbody//*[@class='column-50']"
},
table_cell_traversing: {
css: "table#large-table tbody tr td:nth-of-type(50)",
xpath: "//table[@id='large-table']//tbody//tr//td[50]"
},
table_cell_traversing_and_direct_desc: {
css: "table#large-table > tbody > tr > td:nth-of-type(50)",
xpath: "//table[@id='large-table']/tbody/tr/td[50]"
}
}
attr_reader :driver
def initialize(driver)
@driver = driver
visit '/large'
is_displayed?(id: 'siblings')
super
end
# The benchmarking approach was borrowed from
# http://rubylearning.com/blog/2013/06/19/how-do-i-benchmark-ruby-code/
def benchmark
Benchmark.bmbm(27) do |bm|
LOCATORS.each do |example, data|
data.each do |strategy, locator|
bm.report(example.to_s + " using " + strategy.to_s) do
begin
ENV['iterations'].to_i.times do |count|
find(strategy => locator)
end
rescue Selenium::WebDriver::Error::NoSuchElementError => error
puts "( 0.0 )"
end
end
end
end
end
end
end
注意 :输出是在几秒钟内,其结果是100所执行的总运行时间。
以表格的形式:
以图表形式:
您可以执行基准标记上自己的,使用这个库 ,其中戴夫Haeffner包裹起来的所有代码。