根据我的理解,CSS选择器遍历DOM。因为CSS文件没有关于元素位置的任何信息,所以为什么 cssSelector 比 XPath (理论上)更快。
理论上 cssSelector 占用的时间少于 XPath ,因为 XPath 需要遍历HTML DOM。 XPath 我们可以在DOM层次结构中向后或向前搜索元素,而 CSS 只能在向前方向工作。
但是如果 cssSelector 也遍历HTML DOM,那么它如何使 cssSelector 更快。
换句话说, cssSelector 实际上是如何在内部工作的,并说明为什么它总是优先/建议每个人使用 xpath
另外,请分享使用 cssSelector 而非 XPath 的其他好处。
反之亦然, XPath 区域比 cssSelector
更好答案 0 :(得分:7)
我已经阅读了很多文章,我看过像this和this这样的数据,这些数据显示CSS选择器速度更快,我做了一些测试并且已经来了得出同样的结论。我在2016年12月与elementalselenium.com的作者Dave Haeffner进行了交谈,并向他询问了他网站上的人数(在我上面链接的帖子中),因为他们已经很老了。他更新了测试和CSS选择器的linked me a presentation(参见第18-23页)仍然更快,但XPath正在赶上一些配置。
所以我们可以看到证据证明这是真的,但我从未见过有人谈论为什么的技术细节。如果我猜测,那将是因为很多工作已经进入不同的浏览器以优化页面渲染的速度。让CSS选择器快速工作会使页面渲染速度更快,并且由于浏览器驱动程序利用浏览器定位元素的能力,这意味着CSS选择器通常会获胜。我已经读过一些浏览器已经提高了他们的XPath定位器速度,但我认为它可能总是落后于CSS选择器,因为它只比CSS选择器少得多。
CSS选择器和XPath都必须遍历DOM,因此除了执行遍历的引擎速度之外,没有其他区别。由于CSS选择器的广泛使用,CSS选择器引擎在这一点上可能是微调机器与XPath引擎。
我的常规定位器策略首先是ID,其他所有内容都是CSS选择器。没有其他工作我使用XPath。它会因站点而异,但根据我的经验,ID可能是我定位器的10%左右。 CSS选择器可能约为80%,最后10%是XPath。当我需要通过包含的文本定位元素时,我通常使用XPath,并且很少使用DOM遍历。我的XPath用法的一个例子可能是我需要在TABLE中找到一个相对于行标签的元素,例如:表格行中的奶酪价格,其中第一个单元格包含“奶酪”,第三个单元格包含价格。
我认为XPath在SO和许多博客等网站上都有很多,因为它易于访问。我所要做的就是右键单击devtools中的元素并复制XPath。这个问题很多次会产生一个糟糕的,脆弱的XPath。手工制作的XPath更好,但手工制作一个好的XPath或CSS选择器需要时间和经验。许多人不愿意投入的时间。精心设计的CSS选择器或XPath也会让事情变得更慢。很多时候,元素可以通过多种方式定位,有些方式比其他方式更有效......它取决于定位器的效率以及如何使用它。一个格式错误的CSS选择器不会自动比一个格式良好的XPath更快。
答案 1 :(得分:1)
cssSelector 与 XPath 之间的争论现在仍然是 Selenium社区中最激烈,主观的话题之一。快速回顾一下到目前为止我们已经知道的内容:
Dave Haeffner 在test上进行了a page with two HTML data tables,写了一张没有有用属性( ID 和 Class ),另一个与他们一起。我在讨论Why should I ever use CSS selectors as opposed to XPath for automated testing?中详细分析了测试程序和该实验的结果。尽管该实验表明每个Locator Strategy在浏览器中都相当等效,但它并不能为我们充分描绘整个画面。
Dave Haeffner 在讨论Css Vs. X Path, Under a Microscope中提到,在端到端测试中,还有许多其他变量在起作用 Sauce startup , 浏览器启动,然后等待时间往返于被测试的应用程序。该实验的不幸结果是,一个驱动程序可能比另一个驱动程序更快(例如, IE 与 Firefox ),而实际上并非如此。为了真正了解 cssSelector 和 XPath 之间的性能差异,我们需要更深入地研究。这可以通过使用性能基准标记实用程序运行本地计算机上的所有内容来实现。重点是特定的Selenium动作,而不是整个测试运行,并且运行多次。
为演示此详细示例,已安装Windows XP虚拟机并安装了Ruby (1.9.3)。还安装了所有可用的Selenium浏览器及其等效的浏览器驱动程序。对于基准测试,使用了Ruby的标准库benchmark
。
为了获得足够的数据样本集,对每个浏览器进行了相同的测试100次。为了清除数据中的异常,使用了基准测试的排练功能,以便它可以运行完整测试序列,执行垃圾收集,然后再次运行。为了使事情具有可比性,对一些定位器进行了更新,以使彼此之间的匹配更好。我们测量的具体操作是 find_element
。
require_relative 'base'
require 'benchmark'
class SmallDOM < Base
LOCATORS = {
:id => {
id: 'table2'
},
:table_header_class => {
class: 'dues'
},
:table_header_id_and_class => {
:css => "#table2 thead .dues",
:xpath => "//table[@id='table2']//thead//*[@class='dues']"
},
:table_header_id_class_and_direct_desc => {
:css => "#table2 > thead .dues",
:xpath => "//table[@id='table2']/thead//*[@class='dues']"
},
:table_header_traversing => {
:css => "#table2 thead tr th:nth-of-type(4)",
:xpath => "//table[@id='table2']//thead//tr//th[4]"
},
:table_header_traversing_and_direct_desc => {
:css => "#table2 > thead > tr > th:nth-of-type(4)",
:xpath => "//table[@id='table2']/thead/tr/th[4]"
},
:table_cell_id_and_class => {
:css => "#table2 tbody .dues",
:xpath => "//table[@id='table2']//tbody//*[@class='dues']"
},
:table_cell_id_class_and_direct_desc => {
:css => "#table2 > tbody .dues",
:xpath => "//table[@id='table2']/tbody//*[@class='dues']"
},
:table_cell_traversing => {
:css => "#table2 tbody tr td:nth-of-type(4)",
:xpath => "//table[@id='table2']//tbody//tr//td[4]"
},
:table_cell_traversing_and_direct_desc => {
:css => "#table2 > tbody > tr > td:nth-of-type(4)",
:xpath => "//table[@id='table2']/tbody/tr/td[4]"
}
}
attr_reader :driver
def initialize(driver)
@driver = driver
visit '/tables'
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
find(strategy => locator)
end
rescue Selenium::WebDriver::Error::NoSuchElementError
puts "( 0.0 )"
end
end
end
end
end
end
end
注意:输出以秒为单位,结果为100次执行的总运行时间。
即使存在这些速度差异,它们之间也只有几秒钟(或几分之一秒)的间隔-而且可以执行100次。考虑完成测试运行需要30秒或更长时间时,这种差异可以忽略不计。因此,在css-selectors和xpath之间进行选择可能很难。但是现在,您拥有的数据量足以为自己做出选择。实际上,这只是找到对您和您的团队有用的问题,而不会被关于哪个更好的炒作和观点所困扰。
答案 2 :(得分:-1)
我总是使用xpath。使用xpath,我可以使用对象的任何属性,包括其ID或Name。我可以使用它们的组合和子集,并在需要时调用xpath的强大语言。
根据我的经验,与使用CSS相比,使用xpath导航DOM树是一种更好的定位对象的方法,毕竟CSS仅用于描述其显示方式。
对于速度比较,我认为这将取决于表达式的复杂性。 find_element_by_id('myID')
或find_element_by_xpath(@id='myID')
或find_element_by_css_selector ('myID')
是否调用不同的引擎并产生不同的响应时间?
我听到和读到的有关xpath的很多负面新闻是因为人们使用诸如//div[1]/div[2]/a[3]
这样的硬编码路径,这很脆弱。可以编写更健壮的xpath表达式,例如//div[@id='main']//a[@href='xpath_nodes.asp']
。