将Selenium注释映射到Spring Bean

时间:2018-01-21 18:35:37

标签: java spring selenium

我正在使用Selenium来完成我的一些自动化工作。我使用基于页面对象模型(POM)的方法来定义我的WebElement属性。

@FindBy(id = "username")
private WebElement usernameText;

@FindBy(css = "password")
private WebElement passwordText;

我不希望在类中直接指定注释参数(id = username和css = password)。

是否可以将它们移动到Spring中的bean属性文件中,以便我可以将这些注释映射到bean对象。

例如,我可以定义一个bean对象来传递id和css值,这些值应该在我的Java类中自动连接到这个对象。

1 个答案:

答案 0 :(得分:0)

我实际上并没有看到如何让WebElement实例ApplicationContext知道,因为WebElement没有Spring bean依赖关系。尽管让我们看看我们为实现目标必须做些什么:

  1. 每次WebElement由Selenium创建时,此实例的BeanDefinition范围prototype也应创建,并且应在BeanDefinitionRegistry <中使用唯一名称进行注册/ LI>
  2. 创建BeanDefinition后,应在WebElement内懒洋洋地创建相应的ApplicationContext实例,因为DOM中WebElement可能在创建时不存在。此外,在这个阶段我们必须以某种方式提供定位器
  3. 由于您在单个Page Object中有很多WebElement,因此您将无法按类型注入WebElement实例。因此,您必须在字段+ @Qualifier注释上使用@Resource@Lazy注释来进行延迟bean初始化。每个WebElement字段
  4. 至少有2个注释
  5. ...
  6. 你看到它有多复杂吗?

    从我的角度来看,您无需将WebElement放入ApplicationContext。一些可能有用的东西:

    • 如果页面工厂模式使用情况为您的页面对象实施BeanPostProcessor,并从那里调用PageFactory.initElements(..)。就是这样
    • 删除@FindBy注释并仅使用Page Object模式。您可以将定位器存储为By中的enum个对象。如果您愿意,将enum存储为特定页面对象的嵌套类或单独的类是很方便的。您可以使用By检索这些WebElementFactory个对象。

    以下示例:

    public interface Labeled {
        String label();
    }
    
    public interface ByAware {
        By locator();
    }
    
    public interface WebElementDescriptor extends ByAware, Labeled {
    }
    
    @Component("pageObject")
    public class PageObject {
    
        @Autowired
        private WebElementFactory factory;
    
        public PageObject login(String name, String password) {
            factory.getWebElement(Element.USERNAME_FIELD).sendKeys(name);
            factory.getWebElement(Element.PASSWORD_FIELD).sendKeys(password);
            return this;
        }
    
        enum Element implements WebElementDescriptor {
            USERNAME_FIELD(By.id("username"), "User name input field"),
            PASSWORD_FIELD(By.cssSelector("password"), "Password input field");
    
            private By by;
    
            private String label;
    
            Element(By by, String label) {
                this.by = by;
                this.label = label;
            }
    
            @Override
            public String label() {
                return label;
            }
    
            @Override
            public By locator() {
                return by;
            }
    
        }
    
    }
    
    @Component("webElementFactory")
    public class WebElementFactory {
    
        @Autowired
        private WebDriver driver;
    
        public WebElement getWebElement(WebElementDescriptor descriptor) {
            System.out.println("Processing " + descriptor.label());
            return driver.findElementBy(descriptor.locator());
        }
    
    }