Comment implémenter des méthodes WebDriver PageObject pouvant renvoyer des objets PageObject différents
J'ai commencé à utiliser WebDriveret je suis en train d'apprendre les meilleures pratiques, en particulier à l'aide de PageObjects et PageFactory.
C'est ma compréhension que PageObjects devrait exposer les différentes opérations sur une page web, et d'isoler le WebDriver code à partir de la classe de test. Assez souvent, la même opération peut entraîner la navigation sur des pages différentes selon les données utilisées.
Par exemple, dans cette hypothétique de Connexion scénario, en fournissant des informations d'identification d'administrateur vous emmène à la AdminWelcome page, et fournir au Client des informations d'identification vous emmène à la CustomerWelcome page.
Donc, le plus simple à mettre en œuvre c'est pour exposer deux méthodes qui renvoient des différents PageObjects...
Connexion PageObject
package example;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
public class Login {
@FindBy(id = "username")
private WebElement username;
@FindBy(id = "password")
private WebElement password;
@FindBy(id = "submitButton")
private WebElement submitButton;
private WebDriver driver;
public Login(WebDriver driver){
this.driver = driver;
}
public AdminWelcome loginAsAdmin(String user, String pw){
username.sendKeys(user);
password.sendKeys(pw);
submitButton.click();
return PageFactory.initElements(driver, AdminWelcome.class);
}
public CustomerWelcome loginAsCustomer(String user, String pw){
username.sendKeys(user);
password.sendKeys(pw);
submitButton.click();
return PageFactory.initElements(driver, CustomerWelcome.class);
}
}
Et effectuez les opérations suivantes dans la classe de test:
Login loginPage = PageFactory.initElements(driver, Login.class);
AdminWelcome adminWelcome = loginPage.loginAsAdmin("admin", "admin");
ou
Login loginPage = PageFactory.initElements(driver, Login.class);
CustomerWelcome customerWelcome = loginPage.loginAsCustomer("joe", "smith");
Approche Alternative
Au lieu de la duplication de code, j'espérais qu'il y a une manière plus propre de l'exposition d'une seule login()
méthode qui a renvoyé l'pertinentes PageObject.
J'ai pensé à créer une hiérarchie de pages (ou de les faire mettre en œuvre une interface) pour que je puisse l'utiliser comme type de retour, mais il se sent maladroit. Ce que j'ai trouvé est le suivant:
public <T> T login(String user, String pw, Class<T> expectedPage){
username.sendKeys(user);
password.sendKeys(pw);
submitButton.click();
return PageFactory.initElements(driver, expectedPage);
}
Ce qui signifie que vous pouvez effectuer les opérations suivantes dans la classe de test:
Login loginPage = PageFactory.initElements(driver, Login.class);
AdminWelcome adminWelcome =
loginPage.login("admin", "admin", AdminWelcome.class);
ou
Login loginPage = PageFactory.initElements(driver, Login.class);
CustomerWelcome customerWelcome =
loginPage.login("joe", "smith", CustomerWelcome.class);
C'est flexible - vous pouvez ajouter un ExpiredPassword page et ne pas avoir à changer le login()
méthode à tous - il suffit d'ajouter un autre test et passer à la appropriée expiré informations d'identification et le ExpiredPassword page que la page prévue.
Bien sûr, vous pourriez très facilement quitter la loginAsAdmin()
et loginAsCustomer()
méthodes et remplacer son contenu par un appel à la générique login()
(ce qui serait alors privé). Une nouvelle page (par exemple, la ExpiredPassword page) exigerait alors une autre méthode (par exemple,loginWithExpiredPassword()
).
Cela a l'avantage que la méthode noms signifient réellement quelque chose (vous pouvez facilement voir qu'il y a 3 résultats possibles de la connexion), PageObject de l'API est un peu plus facile à utiliser (pas de "page prévue" pour passer), mais le WebDriver code est toujours d'être réutilisées.
D'autres améliorations...
Si vous n'avez exposer le seul login()
méthode, vous pouvez le rendre plus évidentes les pages qui peut être atteint à partir de la connexion par l'ajout d'un marqueur de l'interface de ces pages (ce n'est probablement pas nécessaire si vous exposer une méthode pour chaque scénario).
public interface LoginResult {}
public class AdminWelcome implements LoginResult {...}
public class CustomerWelcome implements LoginResult {...}
Et mise à jour de la méthode de connexion:
public <T extends LoginResult> T login(String user, String pw,
Class<T> expectedPage){
username.sendKeys(user);
password.sendKeys(pw);
submitButton.click();
return PageFactory.initElements(driver, expectedPage);
}
Une ou l'autre approche semble fonctionner bien, mais je ne suis pas sûr de savoir comment elle sera mise à l'échelle pour des scénarios plus complexes. Je n'ai pas vu des exemples de code comme ça, alors je me demandais ce que tout le monde fait des actions sur une page peut donner des résultats différents en fonction des données?
Ou est-ce une pratique courante de simplement dupliquer le WebDriver code et d'exposer beaucoup de méthodes différentes pour chaque permutation de données/PageObjects?
source d'informationauteur James Bassett
Vous devez vous connecter pour publier un commentaire.
Bohème, la réponse n'est pas flexible - vous ne pouvez pas avoir une page d'action de retourner à la même page (telle que la saisie d'un mauvais mot de passe), et vous ne pouvez pas avoir plus de 1 action de la page différentes pages (pensez à quel gâchis que vous auriez si la page de Connexion a une autre action qui a abouti à des résultats différents). Vous aussi vous retrouver avec des tas d'autres PageObjects juste pour répondre à des résultats différents.
Après la mise à l'essai cette, certains plus (et notamment l'échec de la connexion scénario), je me suis installé sur les points suivants:
Cela signifie que vous pouvez réutiliser la connexion logique, mais éviter la nécessité pour la classe de test pour passer à la page, ce qui signifie que la classe de test est très lisible:
Avoir des méthodes distinctes pour chaque scénario fait aussi de l'
Login
PageObject de l'API très clair et il est très facile de dire à tous les résultats de l'exploitation forestière. Je ne vois pas de valeur en utilisant les interfaces de restreindre les pages utilisées avec lelogin()
méthode.Je serai d'accord avec Tom Anderson qui réutilisables WebDriver code devrait être remaniée en fine des méthodes. S'ils sont exposés finement grainé (donc la classe de test pouvez choisir les opérations concernées), ou combinés et exposé à la classe de test comme un seul gros-grain méthode est sans doute une question de préférence personnelle.
Vous polluent votre API avec plusieurs types de simplement utiliser des génériques et de l'héritage:
et puis
etc pour tous les types sur les pages de connexion
Remarque le travail autour de type d'effacement d'être en mesure de passer une instance de
Class<T>
à laPageFactory.initElements()
méthode, en passant une instance de la classe dans le constructeur, qui est connu comme le "type de jeton" modèle.