Jak zaimplementować metody WebDriver PageObject, które mogą zwracać różne obiekty PageObject

Właśnie zacząłem używaćWebDriveri staram się poznać najlepsze praktyki, w szczególności używającPageObjects iPageFactory.

Rozumiem, że obiekty PageObject powinny ujawniać różne operacje na stronie internetowej i izolować kod WebDriver od klasy testowej. Dość często ta sama operacja może spowodować przejście do różnych stron w zależności od użytych danych.

Na przykład w tym hipotetycznym scenariuszu logowania podanie poświadczeń administratora spowoduje przejście do strony AdminWelcome, a podanie danych uwierzytelniających klienta spowoduje przejście do strony CustomerWelcome.

Najłatwiejszym sposobem na zaimplementowanie tego jest udostępnienie dwóch metod, które zwracają różne obiekty PageObject ...

Zaloguj się 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);
    }

}

I wykonaj następujące czynności w klasie testowej:

Login loginPage = PageFactory.initElements(driver, Login.class);
AdminWelcome adminWelcome = loginPage.loginAsAdmin("admin", "admin");

lub

Login loginPage = PageFactory.initElements(driver, Login.class);
CustomerWelcome customerWelcome = loginPage.loginAsCustomer("joe", "smith");
Alternatywne podejście

Zamiast duplikować kod, miałem nadzieję, że istnieje lepszy sposób na ujawnienie singlalogin() metoda, która zwróciła odpowiedni PageObject.

Pomyślałem o stworzeniu hierarchii stron (lub o zaimplementowaniu interfejsu), aby móc użyć tego jako typu powrotu, ale wydaje się to niezręczne. Wymyśliłem, co następuje:

public <T> T login(String user, String pw, Class<T> expectedPage){
    username.sendKeys(user);
    password.sendKeys(pw);
    submitButton.click();
    return PageFactory.initElements(driver, expectedPage);
}

Co oznacza, że ​​możesz wykonać następujące czynności w klasie testowej:

Login loginPage = PageFactory.initElements(driver, Login.class);
AdminWelcome adminWelcome = 
    loginPage.login("admin", "admin", AdminWelcome.class);

lub

Login loginPage = PageFactory.initElements(driver, Login.class);
CustomerWelcome customerWelcome = 
    loginPage.login("joe", "smith", CustomerWelcome.class);

Jest to elastyczne - możesz dodać stronę ExpiredPassword i nie musisz zmieniaćlogin() metoda w ogóle - wystarczy dodać kolejny test i przekazać odpowiednie poświadczenia, które utraciły ważność, i stronę ExpiredPassword jako oczekiwaną stronę.

Oczywiście możesz łatwo opuścićloginAsAdmin() iloginAsCustomer() metody i zastąp ich zawartość wywołaniem ogólnymlogin() (które następnie stałyby się prywatne). Nowa strona (np. Strona ExpiredPassword) wymagałaby wtedy innej metody (np.loginWithExpiredPassword()).

Ma to tę zaletę, że nazwy metod rzeczywiście coś znaczą (możesz łatwo zauważyć, że istnieją 3 możliwe wyniki logowania), interfejs API PageObject jest nieco łatwiejszy w użyciu (brak „oczekiwanej strony” do przekazania), ale WebDriver kod jest nadal wykorzystywany.

Dalsze doskonalenia...

Jeśli ujawniłeś singiellogin() Metoda ta może sprawić, że stanie się bardziej oczywiste, do których stron można dotrzeć po zalogowaniu się, dodając do nich interfejs znacznika (prawdopodobnie nie jest to konieczne, jeśli ujawnisz metodę dla każdego scenariusza).

public interface LoginResult {}

public class AdminWelcome implements LoginResult {...}

public class CustomerWelcome implements LoginResult {...}

I zaktualizuj metodę logowania, aby:

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);
}

Każde podejście wydaje się działać dobrze, ale nie jestem pewien, jak skalowałoby się to dla bardziej skomplikowanych scenariuszy. Nie widziałem takich przykładów kodu, więc zastanawiam się, co robią wszyscy inni, gdy działania na stronie mogą powodować różne wyniki w zależności od danych?

Czy jest to zwykła praktyka polegająca na duplikowaniu kodu WebDriver i ujawnianiu wielu różnych metod dla każdej permutacji danych / obiektów PageObject?

questionAnswers(2)

yourAnswerToTheQuestion