Szukaj…


Wprowadzenie

Istotna rola w automatyzacji witryn internetowych i aplikacji internetowych polega na identyfikowaniu elementów na ekranie i interakcji z nimi. Przedmioty znajdują się w Selenium dzięki użyciu lokalizatorów i By klasy. Te lokalizatory i interakcje są umieszczane w obiektach strony jako najlepsza praktyka, aby uniknąć powielania kodu i ułatwić konserwację. WebElements i WebElements że zawiera informacje o zachowaniu i zwrocie na stronie (lub części strony w aplikacji internetowej).

Uwagi

Model obiektowy strony to wzorzec, w którym piszemy klasy obiektowe, które służą jako interfejs do konkretnego widoku strony internetowej. Używamy metod tej klasy strony do wykonania wymaganej akcji. Kilka lat temu manipulowaliśmy kodem HTML strony bezpośrednio w klasach testowych, co było bardzo trudne do utrzymania wraz z kruchymi zmianami w interfejsie użytkownika.

Jednak uporządkowanie kodu w taki sposób, aby zawierało wzorzec obiektu strony, zapewnia interfejs API specyficzny dla aplikacji, umożliwiający manipulowanie elementami strony bez konieczności przeszukiwania kodu HTML. Podstawowa ruta kciuka mówi, że obiekt strony powinien zawierać wszystko, co człowiek może zrobić na tej stronie. Na przykład, aby uzyskać dostęp do pola tekstowego na stronie internetowej, powinieneś tam znaleźć metodę, aby uzyskać tekst i zwrócić ciąg znaków po wykonaniu wszystkich modyfikacji.

Kilka ważnych punktów, o których należy pamiętać przy projektowaniu obiektów strony:

  1. Obiekt strony zwykle nie powinien być budowany tylko dla stron, ale powinieneś budować go dla znaczących elementów strony. Na przykład strona z wieloma kartami do wyświetlania różnych wykresów twoich pracowników naukowych powinna mieć taką samą liczbę stron, jak liczba kart.

  2. Przechodzenie z jednego widoku do drugiego powinno zwrócić instancję klas stron.

  3. Metody narzędziowe, które muszą być dostępne tylko dla określonego widoku lub strony internetowej, powinny należeć tylko do tej klasy strony.

  4. Metody asercji nie powinny zajmować się klasami stron, możesz mieć metody zwracające wartość logiczną, ale nie weryfikuj ich tam. Na przykład, aby zweryfikować pełną nazwę użytkownika, możesz mieć metodę uzyskania wartości logicznej:

     public boolean hasDisplayedUserFullName (String userFullName) {
         return driver.findElement(By.xpath("xpathExpressionUsingFullName")).isDisplayed();
     }
    
  5. Jeśli twoja strona oparta jest na iframe, wolę mieć również klasy stron dla iframe.

Zalety wzorca obiektu strony:

  1. Czyste oddzielenie kodu testowego od kodu strony
  2. W przypadku jakiejkolwiek zmiany interfejsu użytkownika strony nie trzeba zmieniać kodu w wielu miejscach. Zmień tylko w klasach stron.
  3. Brak lokalizatorów rozproszonych elementów.
  4. Ułatwia zrozumienie kodu
  5. Łatwa konserwacja

Wprowadzenie (przy użyciu Java)

Przykład wykonania testu logowania na podstawie wzorca obiektu strony:

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;

/**
 * Class which models the view of Sign-In page
 */
public class SignInPage {
    
    @FindBy(id="username")
    private usernameInput;

    @FindBy(id="password")
    private passwordInput;

    @FindBy(id="signin")
    private signInButton;

    private WebDriver driver;

    public SignInPage(WebDriver driver) {
        this.driver = driver;
    }
    
    /**
     * Method to perform login
     */
    public HomePage performLogin(String username, String password) {
        usernameInput.sendKeys(username);
        passwordInput.sendKeys(password);
        signInButton.click();
        return PageFactory.initElements(driver, HomePage.class);
    }
}


import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
/**
 * Class which models the view of home page
 */
public class HomePage {
    @FindBy(id="logout")
    private logoutLink;

    private WebDriver driver;

    public HomePage(WebDriver driver) {
        this.driver = driver;
    }
    
    /**
     * Method to log out
     */
    public SignInPage logout() {
        logoutLink.click();
        wait.ForPageToLoad();
        return PageFactory.initElements(driver, SignInPage.class);
    }
}

/**
 * Login test class
 */
public class LoginTest {
    public void testLogin() {
        SignInPage signInPage = new SignInPage(driver);
        HomePage homePage = signInPage.login(username, password);
        signInPage = homePage.logout();
    }
}

DO#

Obiekty strony powinny zawierać zachowanie, zwracać informacje dla asercji i ewentualnie metodę metody stanu gotowości strony podczas inicjalizacji. Selenium obsługuje obiekty stron za pomocą adnotacji. W języku C # wygląda to następująco:

using OpenQA.Selenium;
using OpenQA.Selenium.Support.PageObjects;
using OpenQA.Selenium.Support.UI;
using System;
using System.Collections.Generic;

public class WikipediaHomePage
{
    private IWebDriver driver;
    private int timeout = 10;
    private By pageLoadedElement = By.ClassName("central-featured-logo");

    [FindsBy(How = How.Id, Using = "searchInput")]
    [CacheLookup]
    private IWebElement searchInput;

    [FindsBy(How = How.CssSelector, Using = ".pure-button.pure-button-primary-progressive")]
    [CacheLookup]
    private IWebElement searchButton;

    public ResultsPage Search(string query) 
    {
        searchInput.SendKeys(query);
        searchButton.Click();
    }

    public WikipediaHomePage VerifyPageLoaded() 
    {
        new WebDriverWait(driver, TimeSpan.FromSeconds(timeout)).Until<bool>((drv) =>  return drv.ExpectedConditions.ElementExists(pageLoadedElement));

        return this;
    }
}

uwagi:

  • CacheLookup zapisuje element w pamięci podręcznej i zapisuje zwracanie nowego elementu przy każdym wywołaniu. Poprawia to wydajność, ale nie jest dobre w przypadku dynamicznie zmieniających się elementów.
  • searchButton ma 2 nazwy klas i brak identyfikatora, dlatego nie mogę użyć nazwy klasy ani identyfikatora.
  • Zweryfikowałem, że moje lokalizatory zwrócą mi element, którego chcę, za pomocą Narzędzi programistycznych (dla Chrome), w innych przeglądarkach możesz użyć FireBug lub podobnego.
  • Metoda Search() zwraca inny obiekt strony ( ResultsPage ), ponieważ kliknięcie wyszukiwania przekierowuje na inną stronę.

Model obiektowy strony najlepszych praktyk

  • Utwórz osobne pliki dla nagłówka i stopki (ponieważ są one wspólne dla wszystkich stron i nie ma sensu uczynić ich częścią jednej strony)
  • Zachowaj wspólne elementy (takie jak Wyszukaj / Wstecz / Dalej itp.) W osobnym pliku (Chodzi o to, aby usunąć wszelkie powielanie i zachować logiczną segregację)
  • W przypadku sterownika dobrym pomysłem jest utworzenie oddzielnej klasy Driver i utrzymanie sterownika jako statycznego, aby był dostępny na wszystkich stronach! (Mam wszystkie moje strony rozszerzają DriverClass)
  • Funkcje używane w obiektach PageObjects są podzielone na najmniejszą możliwą porcję, pamiętając o częstotliwości i sposobie ich wywoływania (sposób, w jaki wykonałeś logowanie - chociaż logowanie można podzielić na funkcje enterUsername i enterPassword, ale nadal je zachowuje ponieważ funkcja logowania jest bardziej logiczna, ponieważ w większości przypadków funkcja logowania byłaby wywoływana zamiast oddzielnych wywołań funkcji enterUsername i enterPassword)
  • Użycie samego PageObjects oddziela skrypt testowy od elementuLocators
  • Mają funkcje narzędziowe w osobnym folderze utils (np. DateUtil, excelUtils itp.)
  • Mają konfiguracje w osobnym folderze conf (np. Ustawienie środowiska, w którym należy uruchomić testy, konfiguracja folderów wyjściowych i wejściowych)
  • Dołącz ekran Przechwyć w razie awarii
  • Posiadaj statyczną zmienną oczekiwania w DriverClass z pewnym niejawnym czasem oczekiwania, tak jak zrobiłeś Zawsze staraj się mieć oczekiwania warunkowe, a nie oczekiwania statyczne, takie jak: wait.until (ExpectedConditions). Dzięki temu oczekiwanie nie niepotrzebnie spowalnia wykonanie.


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow