是什么这是相对于更好地表现为跨浏览器测试cssSelector与XPath和区别?是什么这是相对于更

2019-05-08 15:53发布

我与硒的webdriver 2.25.0工作多语言的Web应用程序和主要测试页面内容(如阿拉伯语,英语,俄语和等不同的语言)。

对于我的应用程序,它是更好的根据性能和确保它应该是所有的浏览器的支持(即IE 7,8,9,FF,铬等)。

在此先感谢您的建议,居停。

Answer 1:

CSS选择器执行远比Xpath的更好,它在硒的社区有据可查。 这里有一些原因,

  • Xpath的发动机在每个浏览器不同,因此让他们不一致
  • IE浏览器没有原生XPath引擎,因此硒注入了自己的XPath引擎其API的兼容性。 因此,我们失去了使用webdriver的内在促进原生浏览器功能的优势。
  • Xpath的往往会变得复杂,从而使硬盘在我看来,阅读

但也有一些地方,你需要使用XPath,例如,寻找一个父元素或它的文本搜索元素的情况下(我不推荐的更新版本)。

您可以从西门阅读博客在这里 。 他还建议在CSS的Xpath。

如果您正在测试的内容则不要使用依赖于元素的内容选择。 这将是一个维护的噩梦了各个地区。 尝试与开发人员和采用的技术,他们使用的外部化在应用程序中的文本,如字典或资源包等说话这里是我的博客 ,解释得很详细。

编辑1

由于@parishodak,这里是链接提供的数字证明了CSS性能更好



Answer 2:

我要保持不受欢迎的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一个,如果我知道它会做的工作就好了。



Answer 3:

VS 的XPath cssSelector之间的争论将继续作为硒社区最主观的辩论之一。 我们已经知道,到目前为止哪些可以概括为:

  • 赞成cssSelector的人说这(尤其是对Internet Explorer中运行时)是更具可读性和速度更快。
  • 而赞成的XPath的吹捧它与横向的页面的能力(而cssSelector不能)。
  • 在旧的浏览器IE8一样遍历DOM不cssSelector工作,但罚款是使用XPath。
  • XPath的可以走了DOM(例如,从孩子父母),而cssSelector只能向下遍历的DOM(例如,从父到子)
  • 但是不能够穿越与cssSelector的DOM在旧的浏览器并不一定是一件坏事,因为它更是你的页面有设计缺陷,可以从一些有用的标记受益的一个指标。
  • 本·伯顿提到,因为这是如何构建应用程序,你应该使用cssSelector。 这使得测试更容易写,谈,和让别人帮助维持。
  • 亚当古彻说,采取更为混合的方法-首先关注的标识,并cssSelector,只有当你需要它利用XPath的 (如走了DOM)和XPath的永远是先进的定位器更强大。

戴夫Haeffner进行了测试具有两个HTML数据表页 ,一个表而没有有益的属性(ID ),和其他与它们写入。 我分析了试验程序和本实验在讨论细节结局为什么我要永远使用cssSelector选择,而不是XPath的自动化测试? 。 虽然这个实验证明,每一个定位战略是跨浏览器相当于合理,但并未充分画的全貌我们。 戴夫Haeffner在其他讨论的CSS比。 X路径,在显微镜下所提到的,在一个终端到终端的测试有在玩沙司启动了很多其他变量, 浏览器启动 ,并且潜伏期和测试的应用程序。 从实验的不幸外卖可能是一个驱动程序可能会比其他(如IE 火狐 VS)更快,而事实上,这是不是在所有的情况。 为了获得性能上的差异是cssSelectorXPath之间什么是真正的味道,我们需要深入挖掘。 我们这样做,但是使用一种性能基准测试工具将数据从本地机器上运行的一切。 我们还专注于一个特定的硒行动,而不是整个试运行,并运行的东西无数次。 我分析了具体的测试程序和本实验在讨论细节成果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所执行的总运行时间。

以表格的形式:

以图表形式:

  • 火狐

  • Internet Explorer 8中

  • Internet Explorer 9的

  • 互联网浏览器10:

  • 歌剧


分析结果

  • Chrome和Firefox都有明确调整为更快的性能cssSelector。
  • Internet Explorer 8中是cssSelector的大杂烩这是行不通的,一个失控的XPath遍历这需要〜65秒,并没有cssSelector结果比较它针对38第二个表遍历。
  • 在IE中图9和10,XPath是更快的整体。 在Safari中,这是一个折腾了,除了一对夫妇慢遍历使用XPath运行。 而在几乎所有的浏览器, 嵌套的兄弟遍历和表格单元格遍历使用XPath做是一个昂贵的操作。
  • 由于定位器是易碎的和低效的,我们需要避免他们这些不应该是不足为奇。

摘要

  • 总体来说有两种情况,其中XPath是明显高于cssSelector慢。 但他们很容易避免的。
  • 性能差异是稍微有利于CSS选择器用于非IE浏览器和轻微赞成的XPath的IE浏览器。

琐事

您可以执行基准标记上自己的,使用这个库 ,其中戴夫Haeffner包裹起来的所有代码。



文章来源: What is the difference between cssSelector & Xpath and which is better with respect to performance for cross browser testing?