使用页面对象gem和Watir webdriver,我们偶尔在页面上遇到Selenium :: WebDriver :: Error :: StaleElementReferenceError,它会加载一些基本内容,发出ajax请求,并重新填充更多信息(对于页面上的速度幻觉)。
这是因为那里会有一个HTML元素,它会很快消失并在用户真正意识到之前再次出现。
我们使用页面对象的“.when_present”方法在访问之前第一次等到页面上的对象。但是,即使在代码找到元素之后,通常它也会获得陈旧元素错误,因为原始HTML元素消失了,而另一个元素在尝试访问它时再次出现。
我们找到了一种方法,只使用直接的Watir(不是页面对象)。我们基本上捕获了Watir :: Wait.until块中的StaleElementReferenceError。如果它获得异常,则块返回false,Wait.until再次尝试,直到它变为true或最终超时。我们发现这通常是第一次得到陈旧元素(在下面的第3行),从救援中返回false,Wait.until再次执行块,第二次是真的,测试继续进行并通过。
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 }
我真的只是想知道是否有任何类型的页面对象包装器用于此类事情。我找不到任何东西。如果没有,那没关系,因为上述工作。好奇。
由于
答案 0 :(得分:3)
Gayle,很好的问题。此时,如果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。这与您上面的所有代码具有相同的效果。如果错误发生,那么您将再次继续。