在调用元素时捕获异常,然后重试页面工厂

问题描述

我在硒项目中使用了页面工厂和AjaxElementLocatorFactory。每个组件对象都扩展了该类:

public abstract class AbstractComponent {

    public AbstractComponent(WebDriver driver){
        AjaxElementLocatorFactory factory = new AjaxElementLocatorFactory(driver,5);
        PageFactory.initElements(factory,this);
    }
}

为了使测试更加稳定,我想实现try and catch每次我在页面工厂中调用元素时,因此,如果selenium抛出任何类型的异常(如StaleElementReferenceException或ElementnotinteractableException),它将再次尝试几秒钟。

我正在实现这样的东西(超时):

while(true) {
        try {
            this.element.click();
            break;
        }
        catch(Exception e) {
            throw e;
        }
    }

我需要一个通用的解决方案,该解决方案在每次在页面工厂中使用元素时都可以使用。有什么建议吗?

解决方法

您应将工厂返回的扩展名AjaxElementLocator设置为覆盖protected boolean isElementUsable(WebElement element)的位置,默认情况下,该true会返回AjaxElementLocator

除非条件不成立,否则定位器将重新尝试查找元素。因此,您的页面类中不需要额外的代码。

DefaultFieldDecorator中捕获并重新尝试了异常。这基本上与常规定位器有所不同。

您可以找到一些详细信息here

基本上,以上内容足以使您的代码稳定,因为要使测试稳定,您应该了解哪些条件定义了准备进行测试的UI。

但是,如果您需要添加一些重试功能(但请注意,过时的元素永远不会恢复到正常状态),则需要对以下结构进行一些更改:

  1. 扩展proxyForLocator类。有 protected 方法InvocationHandler handler = new LocatingElementHandler(locator);,该方法定义了为您的字段创建代理pbject的逻辑。在该默认实现中,行new LocatingElementHandler(locator);中的行LocatingElementHandler负责处理对页面字段的调用并将其分派到实际对象。
  2. 扩展DefaultFieldDecorator,以便它调用超级方法,但在需要时尝试捕获并重新绑定。
  3. public YourPageClass(SearchContext context) { PageFactory.initElements( new CustomFieldDecorator( new AjaxElementLocatorFactory(context) ),this ); } 的重写方法中,将旧处理程序更改为自定义处理程序。
  4. 初始化页面时,请使用如下代码:
var query = @"{""query"": ""mutation {create_item(board_id: 1111,group_id:\""new_group\"",item_name: \""adding works\"",column_values: \"" {\\\""long_text\\\"": { \\\""text\\\"": \\\""Sample text\\\""}} \"") {id}  }"" }";

上面的方法可以让您更改一个位置(实际上是两个位置:Field Decorator和Invocation Handler),但涵盖了当使用已定位的元素进行操作时可能出现的所有可能的异常。