【问题标题】:Watir StaleElementReferenceError in form in frameWatir StaleElementReferenceError 在框架中的形式
【发布时间】:2012-07-27 10:02:44
【问题描述】:

我只是检查页面上是否存在元素:

sleep 5 # for the page load
form.wait_until_present
next if form.span(:class => "SSSMSGWARNINGTEXT").exists?

form 来自这两行:

browser.goto browser.frame(:name => "TargetContent").src
form = browser.form(:name => "win1")

上一页和当前页都存在form,所以我添加了一个睡眠以确保它具有新页。但是,我的程序仍然因错误而崩溃:

[remote server] resource://fxdriver/modules/web_element_cache.js:5665:in `unknown': Element not found in the cache - perhaps the page has changed since it was looked up (Selenium::WebDriver::Error::StaleElementReferenceError)
from [remote server] file:///var/folders/80/_bwll9x91h7d6c5dp2d3fbb00000gr/T/webdriver-profile20120724-63693-194o52g/extensions/fxdriver@googlecode.com/components/driver_component.js:5354:in `unknown'
from [remote server] file:///var/folders/80/_bwll9x91h7d6c5dp2d3fbb00000gr/T/webdriver-profile20120724-63693-194o52g/extensions/fxdriver@googlecode.com/components/driver_component.js:6597:in `unknown'
from [remote server] file:///var/folders/80/_bwll9x91h7d6c5dp2d3fbb00000gr/T/webdriver-profile20120724-63693-194o52g/extensions/fxdriver@googlecode.com/components/driver_component.js:471:in `unknown'
from /Users/amosng/.rvm/gems/ruby-1.8.7-p370/gems/selenium-webdriver-2.25.0/lib/selenium/webdriver/remote/response.rb:52:in `assert_ok'
from /Users/amosng/.rvm/gems/ruby-1.8.7-p370/gems/selenium-webdriver-2.25.0/lib/selenium/webdriver/remote/response.rb:15:in `initialize'
from /Users/amosng/.rvm/gems/ruby-1.8.7-p370/gems/selenium-webdriver-2.25.0/lib/selenium/webdriver/remote/http/common.rb:59:in `new'
from /Users/amosng/.rvm/gems/ruby-1.8.7-p370/gems/selenium-webdriver-2.25.0/lib/selenium/webdriver/remote/http/common.rb:59:in `create_response'
from /Users/amosng/.rvm/gems/ruby-1.8.7-p370/gems/selenium-webdriver-2.25.0/lib/selenium/webdriver/remote/http/default.rb:65:in `request'
from /Users/amosng/.rvm/gems/ruby-1.8.7-p370/gems/selenium-webdriver-2.25.0/lib/selenium/webdriver/remote/http/common.rb:40:in `call'
from /Users/amosng/.rvm/gems/ruby-1.8.7-p370/gems/selenium-webdriver-2.25.0/lib/selenium/webdriver/remote/bridge.rb:598:in `raw_execute'
from /Users/amosng/.rvm/gems/ruby-1.8.7-p370/gems/selenium-webdriver-2.25.0/lib/selenium/webdriver/remote/bridge.rb:576:in `execute'
from /Users/amosng/.rvm/gems/ruby-1.8.7-p370/gems/selenium-webdriver-2.25.0/lib/selenium/webdriver/remote/bridge.rb:542:in `find_element_by'
from /Users/amosng/.rvm/gems/ruby-1.8.7-p370/gems/selenium-webdriver-2.25.0/lib/selenium/webdriver/common/search_context.rb:42:in `find_element'
from /Users/amosng/.rvm/gems/ruby-1.8.7-p370/gems/watir-webdriver-0.6.1/lib/watir-webdriver/locators/element_locator.rb:85:in `find_first_by_multiple'
from /Users/amosng/.rvm/gems/ruby-1.8.7-p370/gems/watir-webdriver-0.6.1/lib/watir-webdriver/locators/element_locator.rb:32:in `locate'
from /Users/amosng/.rvm/gems/ruby-1.8.7-p370/gems/watir-webdriver-0.6.1/lib/watir-webdriver/elements/element.rb:384:in `locate'
from /Users/amosng/.rvm/gems/ruby-1.8.7-p370/gems/watir-webdriver-0.6.1/lib/watir-webdriver/elements/element.rb:362:in `assert_exists'
from /Users/amosng/.rvm/gems/ruby-1.8.7-p370/gems/watir-webdriver-0.6.1/lib/watir-webdriver/elements/element.rb:37:in `exists?'
from ./my-script.rb:123:in `foo'

当我只是想知道某个元素是否存在时,什么可能导致它抛出错误?

编辑:看来将等待时间延长到 10 秒可以解决问题。由于该页面上有一堆Javascript,我想在执行form.wait_until_present 时页面可能没有开始重新加载,而当执行next if form.span(:class => "SSSMSGWARNINGTEXT").exists? 时,加载页面之间的表单不再存在。至少这是我能想到的这次崩溃的唯一原因......

但问题是,我有几个地方会像这样重新加载页面。在任何地方增加 10 秒的睡眠时间会减慢它到令人难以忍受的爬行速度。如何让程序检测页面何时完全重新加载?

编辑 2:尝试在每次页面重新加载时设置 form

    ...
    form = browser.form(:name => "win1")
    form.wait_until_present
    form.a(:id => "CLASS_SRCH_WRK2_SSR_PB_CLASS_SRCH").click
    form = browser.form(:name => "win1")
    form.wait_until_present
    form.input(:id => "#ICSave").click if form.input(:id => "#ICSave").exists?
    form = browser.form(:name => "win1")
    form.wait_until_present
    ...

还是类似的错误:

[remote server] resource://fxdriver/modules/web_element_cache.js:5665:in `unknown': Element not found in the cache - perhaps the page has changed since it was looked up (Selenium::WebDriver::Error::StaleElementReferenceError)
    from [remote server] file:///var/folders/80/_bwll9x91h7d6c5dp2d3fbb00000gr/T/webdriver-profile20120725-47093-y3nzl8/extensions/fxdriver@googlecode.com/components/driver_component.js:5354:in `unknown'
    from [remote server] file:///var/folders/80/_bwll9x91h7d6c5dp2d3fbb00000gr/T/webdriver-profile20120725-47093-y3nzl8/extensions/fxdriver@googlecode.com/components/driver_component.js:6597:in `unknown'
    from [remote server] file:///var/folders/80/_bwll9x91h7d6c5dp2d3fbb00000gr/T/webdriver-profile20120725-47093-y3nzl8/extensions/fxdriver@googlecode.com/components/driver_component.js:471:in `unknown'
    from /Users/amosng/.rvm/gems/ruby-1.9.3-p194/gems/selenium-webdriver-2.25.0/lib/selenium/webdriver/remote/response.rb:52:in `assert_ok'
    from /Users/amosng/.rvm/gems/ruby-1.9.3-p194/gems/selenium-webdriver-2.25.0/lib/selenium/webdriver/remote/response.rb:15:in `initialize'
    from /Users/amosng/.rvm/gems/ruby-1.9.3-p194/gems/selenium-webdriver-2.25.0/lib/selenium/webdriver/remote/http/common.rb:59:in `new'
    from /Users/amosng/.rvm/gems/ruby-1.9.3-p194/gems/selenium-webdriver-2.25.0/lib/selenium/webdriver/remote/http/common.rb:59:in `create_response'
    from /Users/amosng/.rvm/gems/ruby-1.9.3-p194/gems/selenium-webdriver-2.25.0/lib/selenium/webdriver/remote/http/default.rb:65:in `request'
    from /Users/amosng/.rvm/gems/ruby-1.9.3-p194/gems/selenium-webdriver-2.25.0/lib/selenium/webdriver/remote/http/common.rb:40:in `call'
    from /Users/amosng/.rvm/gems/ruby-1.9.3-p194/gems/selenium-webdriver-2.25.0/lib/selenium/webdriver/remote/bridge.rb:598:in `raw_execute'
    from /Users/amosng/.rvm/gems/ruby-1.9.3-p194/gems/selenium-webdriver-2.25.0/lib/selenium/webdriver/remote/bridge.rb:576:in `execute'
    from /Users/amosng/.rvm/gems/ruby-1.9.3-p194/gems/selenium-webdriver-2.25.0/lib/selenium/webdriver/remote/bridge.rb:542:in `find_element_by'
    from /Users/amosng/.rvm/gems/ruby-1.9.3-p194/gems/selenium-webdriver-2.25.0/lib/selenium/webdriver/common/search_context.rb:42:in `find_element'
    from /Users/amosng/.rvm/gems/ruby-1.9.3-p194/gems/watir-webdriver-0.6.1/lib/watir-webdriver/locators/element_locator.rb:247:in `by_id'
    from /Users/amosng/.rvm/gems/ruby-1.9.3-p194/gems/watir-webdriver-0.6.1/lib/watir-webdriver/locators/element_locator.rb:26:in `locate'
    from /Users/amosng/.rvm/gems/ruby-1.9.3-p194/gems/watir-webdriver-0.6.1/lib/watir-webdriver/elements/element.rb:384:in `locate'
    from /Users/amosng/.rvm/gems/ruby-1.9.3-p194/gems/watir-webdriver-0.6.1/lib/watir-webdriver/elements/element.rb:362:in `assert_exists'
    from /Users/amosng/.rvm/gems/ruby-1.9.3-p194/gems/watir-webdriver-0.6.1/lib/watir-webdriver/elements/element.rb:95:in `click'
    from my-script.rb:471:in `block (2 levels) in foo'
    ...

编辑 3:这是完整的测试脚本:

require 'watir-webdriver'

def foo
  browser = Watir::Browser.new
  browser.driver.manage.timeouts.implicit_wait = 3
  browser.goto "http://schedule.arizona.edu"
  browser.form(:name => "win1").select_list(:name => "CLASS_SRCH_WRK2_STRM$54$").option(:index => 2).select
  browser.goto browser.frame(:name => "TargetContent").src
  form = browser.form(:name => "win1")
  term_select_list = form.select_list(:name => "CLASS_SRCH_WRK2_STRM$54$")
  (1..browser.form(:name => "win1").select_list(:name => "CLASS_SRCH_WRK2_STRM$54$").options.count - 1).each do |term_index|
    (1..term_select_list.options.count - 1).each do |subj_index|
      term_select_list.option(:index => term_index).select
      sleep 1
      form.select_list(:name => "CLASS_SRCH_WRK2_SUBJECT$67$").option(:index => subj_index).select
      sleep 1
      form.checkbox(:id => "CLASS_SRCH_WRK2_SSR_OPEN_ONLY").click
      sleep 1
      form.a(:id => "CLASS_SRCH_WRK2_SSR_PB_CLASS_SRCH").click
      sleep 1
      form.input(:id => "#ICSave").click if form.input(:id => "#ICSave").exists?
      sleep 10
      form.wait_until_present
      next if form.span(:class => "SSSMSGWARNINGTEXT").exists?
      puts "got the form I want!!! do something with it: #{form.html[0..10]}"
      form.a(:id => "CLASS_SRCH_WRK2_SSR_PB_NEW_SEARCH").click
      sleep 1
      form.wait_until_present
    end
  end
  browser.close
  GC.start
end

foo

直到到达 ACCT 才会崩溃,但是当它到达 ACCT 时,它会可靠地崩溃(对我而言),尽管这可能只是因为 1 秒的睡眠时间不够长。

带有form.wait_until_present而不是任意睡眠的脚本:

require 'watir-webdriver'

def foo
  browser = Watir::Browser.new
  browser.driver.manage.timeouts.implicit_wait = 3
  browser.goto "http://schedule.arizona.edu"
  browser.form(:name => "win1").select_list(:name => "CLASS_SRCH_WRK2_STRM$54$").option(:index => 2).select
  browser.goto browser.frame(:name => "TargetContent").src
  form = browser.form(:name => "win1")
  term_select_list = form.select_list(:name => "CLASS_SRCH_WRK2_STRM$54$")
  (1..browser.form(:name => "win1").select_list(:name => "CLASS_SRCH_WRK2_STRM$54$").options.count - 1).each do |term_index|
    (1..term_select_list.options.count - 1).each do |subj_index|
      term_select_list.option(:index => term_index).select
      form = browser.form(:name => "win1")
      form.wait_until_present
      form.select_list(:name => "CLASS_SRCH_WRK2_SUBJECT$67$").option(:index => subj_index).select
      form = browser.form(:name => "win1")
      form.wait_until_present
      form.checkbox(:id => "CLASS_SRCH_WRK2_SSR_OPEN_ONLY").click
      form = browser.form(:name => "win1")
      form.wait_until_present
      form.a(:id => "CLASS_SRCH_WRK2_SSR_PB_CLASS_SRCH").click
      form = browser.form(:name => "win1")
      form.wait_until_present
      form.input(:id => "#ICSave").click if form.input(:id => "#ICSave").exists?
      form = browser.form(:name => "win1")
      form.wait_until_present
      next if form.span(:class => "SSSMSGWARNINGTEXT").exists?
      puts "got the form I want!!! do something with it: #{form.html[0..10]}"
      form.a(:id => "CLASS_SRCH_WRK2_SSR_PB_NEW_SEARCH").click
      form = browser.form(:name => "win1")
      form.wait_until_present
    end
  end
  browser.close
  GC.start
end

foo

在到达 ABE 之前就崩溃了。

【问题讨论】:

  • 既然您使用的是next,这是否意味着这段代码在循环中?该循环中是否有任何操作会导致页面或元素重新加载?
  • @JustinKo 是的,它在一个循环中,是的,有很多动作会导致框架重新加载。这是我的问题——我想等到框架完成重新加载。
  • 您是否在每次重新加载框架时都重新声明form = browser.form(:name => "win1")?我通常在存储元素时看到过时的引用,然后在页面重新加载后尝试使用它们而不重新声明。
  • @JustinKo 啊,不,我不是。我想既然在同一个地方是同一个表格,那没关系,但我想不是。我会试试的。非常感谢!
  • @JustinKo 刚刚试了一下,更新了答案,好像还是不行

标签: ruby frame watir watir-webdriver


【解决方案1】:

有时最好等待某事消失而不是某事出现。在这种情况下,当进行 ajax 调用时,您会得到一个方便的徽标,表明页面正在加载。将所有 sleep 1 替换为以下内容即可完成脚本而不会出现错误。

browser.image(:id, 'processing').wait_while_present

结果似乎有点奇怪,但以下脚本不再遇到您遇到的异常。希望这至少可以帮助您继续前进。

require 'watir-webdriver'

def foo
  browser = Watir::Browser.new
  browser.driver.manage.timeouts.implicit_wait = 3
  browser.goto "http://schedule.arizona.edu"
  browser.form(:name => "win1").select_list(:name => "CLASS_SRCH_WRK2_STRM$54$").option(:index => 2).select
  browser.goto browser.frame(:name => "TargetContent").src
  form = browser.form(:name => "win1")
  term_select_list = form.select_list(:name => "CLASS_SRCH_WRK2_STRM$54$")
  (1..browser.form(:name => "win1").select_list(:name => "CLASS_SRCH_WRK2_STRM$54$").options.count - 1).each do |term_index|
    (1..term_select_list.options.count - 1).each do |subj_index|
      term_select_list.option(:index => term_index).select
      browser.image(:id, 'processing').wait_while_present
      form.select_list(:name => "CLASS_SRCH_WRK2_SUBJECT$67$").option(:index => subj_index).select
      browser.image(:id, 'processing').wait_while_present
      form.checkbox(:id => "CLASS_SRCH_WRK2_SSR_OPEN_ONLY").click
      browser.image(:id, 'processing').wait_while_present
      form.a(:id => "CLASS_SRCH_WRK2_SSR_PB_CLASS_SRCH").click
      browser.image(:id, 'processing').wait_while_present
      form.input(:id => "#ICSave").click if form.input(:id => "#ICSave").exists?
      browser.image(:id, 'processing').wait_while_present
      form.wait_until_present
      next if form.span(:class => "SSSMSGWARNINGTEXT").exists?
      puts "got the form I want!!! do something with it: #{form.html[0..10]}"
      form.a(:id => "CLASS_SRCH_WRK2_SSR_PB_NEW_SEARCH").click
      browser.image(:id, 'processing').wait_while_present
      form.wait_until_present
    end
  end
  browser.close
  GC.start
end

foo

【讨论】:

  • 太棒了。完美运行。非常感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多