Me gusta mucho cómo selenio 2 por convención lo empuja hacia el uso de PageObjects como POJO, y luego simplemente usa PageFactory para crear instancias de los campos en esta clase.Página de Selenio Reutilización de objetos
Lo que estoy encontrando limitante es que reutilizamos muchos elementos en muchas páginas diferentes. El gran problema es que estos componentes reutilizados no tienen el mismo ID/nombre cuando aparecen en páginas diferentes; sin embargo, las pruebas que correríamos para cada una de ellas son las mismas.
Como ejemplo recopilamos fechas en muchos lugares. Por lo tanto un objeto ejemplo, la página de esto podría ser (mes, día campos eliminados):
public class DatePageObject {
private WebDriver driver;
DatePageObject(WebDriver driver) {
this.driver = driver;
}
@FindBy(id = "someIdForThisInstance")
private WebElement year;
public void testYearNumeric() {
this.year.sendKeys('aa');
this.year.submit();
//Logic to determine Error message shows up
}
}
Entonces yo podría simplemente probar esto con el código de abajo:
public class Test {
public static void main(String[] args) {
WebDriver driver = new FirefoxDriver();
DatePageObject dpo = PageFactory.initElements(driver, DriverPageObject.class);
driver.get("Some URL");
dpo.testYearNumeric();
}
}
Lo que realmente me gustaría hacer es tener una configuración mediante la cual con Spring puedo inyectar esa identificación/nombre/xpath, etc ... en la aplicación.
¿Hay alguna forma de que pueda hacer esto, sin perder la capacidad de utilizar PageFactory?
Editar 1 - Agregar las clases de nivel base ideales, trabajando en localizadores personalizados y fábricas.
public class PageElement {
private WebElement element;
private How how;
private String using;
PageElement(How how, String using) {
this.how = how;
this.using = using;
}
//Getters and Setters
}
public class PageWidget {
private List<PageElement> widgetElements;
}
public class Screen {
private List<PageWidget> fullPage;
private WebDriver driver;
public Screen(WebDriver driver) {
this.driver = driver;
for (PageWidget pw : fullPage) {
CustomPageFactory.initElements(driver, pw.class);
}
}
Edición 2 - Así como una nota, siempre y cuando se está ejecutando selenio 2.0.a5 o mayor, ahora se puede dar al conductor un valor de tiempo de espera implícita.
para que pueda reemplazar el código con:
private class CustomElementLocator implements ElementLocator {
private WebDriver driver;
private int timeOutInSeconds;
private final By by;
public CustomElementLocator(WebDriver driver, Field field,
int timeOutInSeconds) {
this.driver = driver;
this.timeOutInSeconds = timeOutInSeconds;
CustomAnnotations annotations = new CustomAnnotations(field);
this.by = annotations.buildBy();
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS); //Set this value in a more realistic place
}
public WebElement findElement() {
return driver.findElement(by);
}
}
Esto definitivamente me ha conseguido en la pista correcta. Tenía la esperanza de extenderlo más allá de las ID's también (podría inyectar cualquier medio necesario y luego ubicarlo). Mi problema era que no estaba viendo cómo se estaban creando esos campos, lo que me estaba haciendo no captar correctamente el ElementLocator. – Scott