【问题标题】:Fetch Pagefactory WebElement name using reflection使用反射获取 Pagefactory WebElement 名称
【发布时间】:2019-08-23 13:57:53
【问题描述】:

我正在使用 selenium pagefactory,并引入了注释 @Name(Description = "Username"),我将其用于所有 WebElements。 稍后我需要在我的自定义方法中找到 Description 的值,以便进行报告,例如:

public static void click(WebElement element) throws Throwable {
        try {
            element.click();
        } catch(ElementNotInteractableException E1) {
            throw new UnableToInteractWithElementException("Unable To Interact With " + WebElement Descriptionn);
        }
    }

我的@Name注解界面和pagefactory是这样的:

名称接口

@Target({ElementType.FIELD, ElementType.TYPE,ElementType.CONSTRUCTOR})
public @interface Name {    
    String Description() default "";
}
@Name(Description = "Username")
@FindBy(id="txtLoginID")
public WebElement username;

我在使用反射时遇到的问题是需要定义 pagefactory 的类名,并提供字段名作为字符串“用户名”,以检索注释值。

我希望能够通过仅向我的 click(WebElement 元素) 方法提供我的 WebElement 而没有其他对象来检索注释值。

【问题讨论】:

  • 我认为在以WebElement 为参数的方法中是不可能的。您还必须传递整个页面对象。 public static void click(Class<? extends PageObject> poClass, WebElement element)。这可以接受吗?

标签: java selenium selenium-webdriver reflection page-factory


【解决方案1】:

我可以向您展示如何使用反射部分获取描述。

首先,我们必须修复注解@Name,因为你没有添加RetentionPolicy

@Target({ElementType.FIELD, ElementType.TYPE, ElementType.CONSTRUCTOR})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Name {
    String Description() default "";
}

现在,我所做和测试的内容是为名称创建存储空间,并在初始化页面对象时存储它们,如下所示:

public class NameStore {
    public static HashMap<WebElement, String> map = new HashMap<>();

    public static void store(Object pageObject) {
        Field[] fields = pageObject.getClass().getDeclaredFields();
        for (Field field : fields) {
            Name annotation = field.getAnnotation(Name.class);
            if (annotation != null) {
                try {
                    map.put((WebElement) field.get(pageObject), annotation.Description());
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static String getDescription(WebElement element) {
        return map.get(element);
    }
}

您将页面对象作为参数传递,@Name 注释被读取并存储到 HashMap&lt;WebElement, String&gt;

初始化存储在构造函数中的名称:

    public PageObject(WebDriver driver) {
        PageFactory.initElements(driver, this);
        NameStore.store(this); //THIS IS CRUCIAL. Also make sure that's always AFTER PageFactory initialization
    }

现在,更新您的 click 方法:

public static void click(WebElement element) throws Throwable {
        try {
            element.click();
        } catch(ElementNotInteractableException E1) {
            throw new UnableToInteractWithElementException("Unable To Interact With " + NameStore.get(element));
        }
    }

希望对你有帮助!

免责声明:我没有在多线程的上下文中对其进行测试。我没有在构造函数的上下文中进行测试。

【讨论】:

  • @abhijit.bhatta 我很确定它不能通过反射实现
  • 是的,我开始有类似的感觉。也许如果我们可以从它的代理中解开 WebElement,我们可能会有更好的运气。
【解决方案2】:

您好,我不是反省专家,我不确定我的问题是否正确。您可能有另一种最佳方法,但遵循一个解决方案,创建一个接收 WebElement 并返回描述的方法:

private static String getDescription(WebElement element) throws IllegalAccessException {
    //Get all the fields of the page object.
    for (Field field : YOUR_PAGE_OBJECT.class.getDeclaredFields()) {
        Name name = field.getAnnotation(Name.class);
        //Consider only the ones that is annotated by your @Name
        if (name != null) {
            WebElement classElement = (WebElement) field.get(element);
            //Get the element from the class and compare with your current.
            if (classElement != null && (classElement).equals(element)) {
                return name.Description();
            }
        }
    }
    return ":C"; // or throw something, whatever you want...
}

您的代码将如下结束:

public static void click(WebElement element) throws Throwable {
        try {
            element.click();
        } catch(ElementNotInteractableException E1) {
            throw new UnableToInteractWithElementException("Unable To Interact With " + getDescription(element));
        }
    }

【讨论】:

  • 感谢斯宾塞的帮助。我之前尝试过类似的方法,但这不起作用,因为在 pagefactory 中,webelement 被实例化为代理对象,因此尝试将 field.get(element) 转换为 WebElement 会返回 IllegalArgumentException。错误:无法将 org.openqa.selenium.WebElement 字段 com.concerto.rhythm.test.pages.LoginPage.Logo 设置为 com.sun.proxy.$Proxy12。
猜你喜欢
  • 2012-05-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多