如何提高Watir element.present的性能?方法?

如何提高Watir element.present的性能?方法?,watir,watir-webdriver,Watir,Watir Webdriver,我在使用Watir的Ruby脚本时遇到了很大的延迟。以下是问题描述:我正在测试基于AJAX的应用程序,我希望避免使用睡眠来确保页面加载: class Page attr_accessor :expected_elements def loaded? # code to make sure AJAX page is loaded end end 因此,与此相反: def loaded? # static delay sufficient to get page load

我在使用Watir的Ruby脚本时遇到了很大的延迟。以下是问题描述:我正在测试基于AJAX的应用程序,我希望避免使用睡眠来确保页面加载:

class Page
  attr_accessor :expected_elements

  def loaded?
    # code to make sure AJAX page is loaded
  end
end
因此,与此相反:

def loaded?
  # static delay sufficient to get page loaded
  sleep(MAX_PAGE_LOAD_TIME)
  true
end
我想要这样的东西:

def loaded?
  Watir::Wait.until(MAX_PAGE_LOAD_TIME) do
    expected_elements.all? do |element|
      element.present?
    end
  end
end
问题是对区块的评估时间太长。我检查的元素越多,延迟就越高。我大致经历了一次迭代的延迟:

Firefox -> 130ms
IE -> 615ms
Chrome -> 115 ms
所以为了检查是否存在N个元素,我得到了N倍的相应延迟。。。结果是,即使MAX_PAGE_LOAD_TIME过期,Watir::Wait::TimeoutError也不会抛出,因为块求值尚未完成。。。因此,我最终遇到了这样的情况,即检查元素的存在引入了比静态延迟更高的延迟,静态延迟足以加载页面。。我试图通过xpath定位元素来提高性能,但性能提升并不显著。。 我做错了什么?目前有没有办法加快执行时间?方法??这些延迟是否与您的经验相符?或者是否很高

我检查了问题是否存在于浏览器-服务器通信中,但这里的延迟非常低。。我得到了100毫秒的服务器响应时间差,包括后端数据库请求。当然,基于此响应呈现页面需要一些时间,但可以肯定的是,这不会花费几秒钟的时间

我的配置: -Win7操作系统, -Firefox17.0.1 -IE 8.0.7601.17514和IEDriverServer_x64_2.26.2 -Chrome 23.0.1271.97米,带chromedriver_win_23.0.1240.0, -Ruby 1.9.3p125, -watir webdriver(0.6.1), -selenium webdriver(2.27.2)

谢谢你的帮助

根据讨论,我发布了一个基准测试代码示例:

Benchmark.bm do |x|
  x.report("text") do
    b.span(:text => "Search").present?
  end
end
Benchmark.bm do |x|
  x.report("xpath") do
    b.span(:xpath => "/html/body/div/div/div[2]/div[2]/div/div/div/div/div/div/div/div[2]/div/div/div[2]/div/div/div/div/div/div[2]/div/div/div/div/div/div/div/div[2]/div/div/div[2]/div/div/div/div/div/div[2]/div/div/div/div/div/span/span").present?
  end
end

        user     system      total        real
text   0.000000   0.000000   0.000000 (  0.140405)
xpath  0.000000   0.000000   0.000000 (  0.120005)
其他基准测试结果:

container_xpath = "/html/body/div/div/div[2]/div[2]/div/div/div/div/div/div/div/div[2]/div/div/div[2]/div/div/div/div/div/div[2]/div/div/div/div/div/div/div/div/div/div/div/div/div/div/div[2]/div/div/div/div[2]/div/div/div"
Benchmark.bm do |x|
  x.report("cntnr") do
    @c = b.div(:xpath => container_xpath)
    @c.present?
  end
end
Benchmark.bm do |x|
  x.report("lb1") do
    @c.div(:xpath => "div[1]/div/div").present?
    #@c.div(:text => "Company:").present?
  end
end
Benchmark.bm do |x|
  x.report("lb2") do
    @c.div(:xpath => "div[3]/div/div").present?
    #@c.div(:text => "Contact person:").present?
  end
end
Benchmark.bm do |x|
  x.report("lb3") do
    @c.div(:xpath => "div[5]/div/div").present?
    #@c.div(:text => "Address:").present?
  end
end
结果是:

Results for container reference and relative xpath:
       user     system      total        real
cntnr  0.000000   0.000000   0.000000 (  0.156007)
lb1    0.000000   0.000000   0.000000 (  0.374417)
lb2    0.000000   0.000000   0.000000 (  0.358816)
lb3    0.000000   0.000000   0.000000 (  0.358816)

Results for container reference and div's text:
       user     system      total        real
cntnr  0.000000   0.000000   0.000000 (  0.140402)
lb1    0.000000   0.000000   0.000000 (  0.358807)
lb2    0.000000   0.000000   0.000000 (  0.358807)
lb3    0.000000   0.000000   0.000000 (  0.374407)
       user     system      total        real
cntnr  0.000000   0.000000   0.000000 (  0.140404)
lb1_x  0.000000   0.000000   0.000000 (  0.124804)
lb2_x  0.000000   0.000000   0.000000 (  0.156005)
lb3_x  0.000000   0.000000   0.000000 (  0.140405)
使用绝对XPath时:

container_xpath = "/html/body/div/div/div[2]/div[2]/div/div/div/div/div/div/div/div[2]/div/div/div[2]/div/div/div/div/div/div[2]/div/div/div/div/div/div/div/div/div/div/div/div/div/div/div[2]/div/div/div/div[2]/div/div/div"
Benchmark.bm do |x|
  x.report("cntnr") do
    @c = b.div(:xpath => container_xpath)
    @c.present?
  end
end

lb1_xpath = container_xpath + "/div[1]/div/div"
Benchmark.bm do |x|
  x.report("lb1_x") do
    b.div(:xpath => lb1_xpath).present?
  end
end

lb2_xpath = container_xpath + "/div[3]/div/div"
Benchmark.bm do |x|
  x.report("lb2_x") do
    b.div(:xpath => lb2_xpath).present?
  end
end

lb3_xpath = container_xpath + "/div[5]/div/div"
Benchmark.bm do |x|
  x.report("lb3_x") do
    b.div(:xpath => lb3_xpath).present?
  end
end
结果如下:

Results for container reference and relative xpath:
       user     system      total        real
cntnr  0.000000   0.000000   0.000000 (  0.156007)
lb1    0.000000   0.000000   0.000000 (  0.374417)
lb2    0.000000   0.000000   0.000000 (  0.358816)
lb3    0.000000   0.000000   0.000000 (  0.358816)

Results for container reference and div's text:
       user     system      total        real
cntnr  0.000000   0.000000   0.000000 (  0.140402)
lb1    0.000000   0.000000   0.000000 (  0.358807)
lb2    0.000000   0.000000   0.000000 (  0.358807)
lb3    0.000000   0.000000   0.000000 (  0.374407)
       user     system      total        real
cntnr  0.000000   0.000000   0.000000 (  0.140404)
lb1_x  0.000000   0.000000   0.000000 (  0.124804)
lb2_x  0.000000   0.000000   0.000000 (  0.156005)
lb3_x  0.000000   0.000000   0.000000 (  0.140405)

好的,这个答案假设您的站点正在使用jquery。如果不是,您必须找出正在使用的库,并相应地修改该方法

编写一个等待Ajax调用完成的方法

def wait_for_ajax(timeout = 10)
  timeout.times do
    return true if browser.execute_script('return jQuery.active').to_i == 0
    sleep(1)
  end

  raise Watir::Wait::TimeoutError, "Timeout of #{timeout} seconds exceeded on waiting for Ajax."
end

第一次加载要测试的页面时调用该方法。然后遍历期望的元素,看看它们是否存在(如果要检查Watir元素数组,请确保使用。每个元素都有,而不是。所有?就像代码中的那样)。

为什么要将元素检查包装在等待内容中?为什么不编写一个方法,等待所有ajax调用完成,然后检查是否存在期望的元素呢?我对Watir不太熟悉,我认为使用Watir::Wait.until将是一种“看门狗”超时的方法,在此时间内,对html元素的存在进行100毫秒的轮询。“最大页面加载时间”用于替换默认的30秒超时。我希望轮询能够在所有预期元素加载时快速发现。。我不知道WatirAPI允许您连接AJAX调用,或者在所有AJAX调用完成时检测情况。我可以请您提供使用这种方法的简短代码示例,或者提供链接参考吗?您不可能知道页面上最后加载的元素是什么吗?当涉及到性能问题时,给出一个实际的示例确实很有帮助。页面的大小、正在检查的元素数量以及用于元素的定位器都会影响性能。也就是说,我通常只会检查我想要与之交互的元素,而不是检查页面上的所有内容。出于好奇,您是否也可以对watir classic进行基准测试?一种加速的方法是为元素设置非常特定的定位器-首先设置一个带有
:id
的容器,比如
container=browser.div(:id=>“我的容器”)
以避免每次搜索整个DOM。接下来搜索该容器中的元素
container.div(:class=>“我的预期元素”)
。因此,请尽可能使用
:id
,并尝试缩小查找元素的DOM范围。谢谢您的帮助。问题是我不是JS人,我正在测试的应用程序是基于GWT的,所以它会转换为原生JS。还有一个开放点——您的提案建议在没有AJAX请求挂起时进行状态投票,然后检查元素是否存在。但同样的事情也应该通过使用until/until_-present方法来完成。我只是轮询以检查元素的存在,当没有挂起的AJAX请求时,这些元素返回true。所以我给你1+的新信息,关于Watir如何与JS框架对话。但如果有其他评论,我会等待。谢谢你的投票,尽管我真的很想给你一个答案,在这里。:)另一个问题是:典型的元素定义是什么样的?如果您在标识元素时使用了大量正则表达式,或者它们包含在页面的表中,那么速度可能会慢很多。看看Justin Ko对这个问题的回答,讨论如何使用nokogiri来提高性能,在这种情况下:实际上我没有使用regexp来定位元素。。我还检查了引用的代码-Nokogiri用于获取元素的xpath。但是我尝试通过xpath来定位元素,性能提升并不显著——我使用基准测试gem进行了检查,时间差大约为20ms,支持使用显式xpath。。请查看编辑后的标杆代码示例。问题可能是GWT生成的DOM非常深,只需花那么长的时间就可以遍历它。