4

使用 page-object gem 和 Watir webdriver,我们偶尔会在页面上遇到 Selenium::WebDriver::Error::StaleElementReferenceError,它会加载一些基本内容、发出 ajax 请求并重新填充更多信息(对于速度的错觉在页面上)。

发生这种情况是因为那里会有一个 HTML 元素,它会很快消失并在用户真正意识到之前再次出现。

我们使用页面对象的“.when_present”方法等到对象第一次出现在页面上之后再访问它。然而,即使在代码找到了元素之后,它通常也会收到过时元素错误,因为原来的 HTML 元素已经消失,而另一个元素在它尝试访问它时又重新出现了。

我们找到了一种仅使用直接 Watir(不是页面对象)的方法。我们基本上在 Watir::Wait.until 块中捕获了 StaleElementReferenceError。如果遇到异常,则块返回 false,Wait.until 再次尝试,直到它变为 true 或最终超时。我们发现,这通常第一次获取 Stale Element(在下面的第 3 行),从救援返回 false,Wait.until 再次执行该块,第二次为 true,测试继续并通过.

1  Watir::Wait.until {
2    begin
3      tds = page.my_element.when_present.element.tds
4      table_data_classes = tds.map{|cell| cell.attribute_value("class") }
5
6      # Should have at least one with a class of "xyz"
7      xyz = table_data_classes.select{|data| data.include?("xyz")}
8      xyz.size > 0 
9    rescue Selenium::WebDriver::Error::StaleElementReferenceError
10     false
11   end
12 }

我真的只是想知道这种事情是否有任何类型的页面对象包装器。我什么也找不到。如果没有,那没关系,因为上述方法有效。只是好奇。

谢谢

4

1 回答 1

3

盖尔,好问题。如果 StaleElementReferenceError 发生在页面对象 gem 中,此时没有特定的重试处理。我从另一个人那里听说他们会定期收到此错误,这是我可以调查的。您使用的是什么版本的 watir-webdriver?

有一种方法可以使用 page-object 复制上面的代码。我不确定您提供的上述代码是在您的页面内还是在其他地方(如步骤定义或其他地方)。这是我使用页面对象 gem 会做的事情:

在您的 PageObject 类内部

def has_element_with_class(clz)
  wait_until
    begin
      cells = my_element.when_present.cell_elements
      cells.any? { |cell| cell.attribute('class').include? clz }
    rescue Selenium::WebDriver::Error::StaleElementReferenceError
      false
  end
end

我只是将所有嵌套在my_element数组中的单元格(tds)。我正在调用该any?数组上的方法,如果任何块返回 true,则返回 true,否则返回 false。这与您上面的所有代码具有相同的效果。如果发生错误,那么您将继续下一次。

于 2013-04-13T14:37:32.717 回答