J'aime vraiment comment le sélénium 2 par convention vous pousse à utiliser PageObjects en tant que POJO, puis en utilisant simplement PageFactory pour instancier les champs de cette classe. Ce que je trouve limitant est que nous réutilisons beaucoup d'éléments sur de nombreuses pages différentes. Le gros problème est que ces composants réutilisés n'ont pas le même identifiant/nom quand ils apparaissent sur des pages différentes; Cependant, les tests que nous ferions pour chacun d'entre eux sont les mêmes. Par exemple, nous collectons des dates dans de nombreux endroits. Ainsi, un objet page d'exemple pour ce qui pourrait être (mois, les champs de jour enlevés):Selenium Page Object Réutilisation
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
}
}
alors je pourrais simplement tester cela avec le code ci-dessous:
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();
}
}
Ce que je voudrais vraiment faire est une configuration par laquelle Spring peut injecter l'identifiant/nom/xpath, etc ... dans l'application.
Y a-t-il un moyen de le faire, sans perdre la possibilité d'utiliser PageFactory?
Édition 1 - Ajout de classes de niveau de base idéales, travaillant sur les localisateurs personnalisés et les usines.
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);
}
}
Edit 2 - Tout comme une note, aussi longtemps que vous utilisez Sélénium 2.0.a5 ou plus, vous pouvez maintenant donner au conducteur une valeur de délai d'attente implicite.
Vous pouvez remplacer votre code avec:
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);
}
}
Cela m'a certainement obtenu sur la bonne piste. J'espérais l'étendre plus loin que juste les ID (vous pouvez injecter tous les moyens nécessaires et ensuite localiser). Mon problème était que je ne voyais pas comment ces Fields étaient créés, ce qui ne me permettait pas de bien saisir l'ElementLocator. – Scott