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