Zoeken…


Invoering

Een belangrijke rol bij het automatiseren van websites en webapplicaties omvat het identificeren van items op het scherm en het ermee omgaan. Items worden gevonden in Selenium door het gebruik van locators en de klasse By . Deze locators en interacties worden als een best practice in Page Objects geplaatst om dubbele code te voorkomen en onderhoud eenvoudiger te maken. Het omvat WebElements en veronderstelt gedrag te bevatten en informatie terug te geven op de pagina (of een deel van een pagina in een web-app).

Opmerkingen

Pagina-objectmodel is een patroon waarin we objectgeoriënteerde klassen schrijven die als interface voor een bepaalde weergave van een webpagina dienen. We gebruiken de methoden van die paginaklasse om de vereiste actie uit te voeren. Enkele jaren geleden manipuleerden we de HTML-code van webpagina's rechtstreeks in testklassen, wat erg moeilijk te onderhouden was, samen met broos aan veranderingen in de gebruikersinterface.

Als uw code echter is georganiseerd op een manier als Pagina-objectpatroon, biedt dit een applicatiespecifieke API, waarmee u de pagina-elementen kunt manipuleren zonder in de HTML te hoeven graven. De eenvoudige vuistregel zegt dat je pagina-object alles moet hebben wat een mens op die webpagina kan doen. Als u bijvoorbeeld toegang wilt krijgen tot het tekstveld op een webpagina, moet u daar een methode gebruiken om de tekst en tekenreeks terug te krijgen nadat u alle wijzigingen hebt doorgevoerd.

Enkele belangrijke punten waarmee u rekening moet houden bij het ontwerpen van de paginaobjecten:

  1. Pagina-object moet meestal niet alleen voor pagina's worden gebouwd, maar u moet er de voorkeur aan geven om het te bouwen voor belangrijke pagina-elementen. Een pagina met meerdere tabbladen om verschillende grafieken van uw academici weer te geven, moet bijvoorbeeld hetzelfde aantal pagina's hebben als het aantal tabbladen.

  2. Navigeren van de ene weergave naar de andere zou het exemplaar van paginaklassen moeten opleveren.

  3. De hulpprogramma's die alleen voor een specifieke weergave of webpagina vereist zijn, moeten alleen tot die paginaklasse behoren.

  4. De beweermethoden moeten niet worden behandeld door paginaklassen, u kunt methoden hebben om Boolean terug te sturen, maar verifieer ze daar niet. Om bijvoorbeeld de volledige gebruikersnaam te verifiëren, kunt u een methode gebruiken om een Booleaanse waarde te krijgen:

     public boolean hasDisplayedUserFullName (String userFullName) {
         return driver.findElement(By.xpath("xpathExpressionUsingFullName")).isDisplayed();
     }
    
  5. Als uw webpagina is gebaseerd op iframe, geeft u de voorkeur aan paginaklassen voor iframes.

Voordelen van pagina-objectpatroon:

  1. Reinig de scheiding tussen testcode en paginacode
  2. In het geval van een wijziging in de gebruikersinterface van de webpagina, hoeft u uw code niet op meerdere plaatsen te wijzigen. Alleen wijzigen in paginaklassen.
  3. Geen verspreide elementzoekers.
  4. Maakt code eenvoudiger te begrijpen
  5. Makkelijk onderhoud

Introductie (Java gebruiken)

Een voorbeeld om een inlogtest uit te voeren op basis van het paginaobjectpatroon:

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

C #

Pagina-objecten moeten gedrag bevatten, informatie retourneren voor beweringen en mogelijk een methode voor de status van de pagina gereed bij initialisatie. Selenium ondersteunt pagina-objecten met behulp van annotaties. In C # is het als volgt:

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

notes:

  • CacheLookup slaat het element op in de cache en slaat bij elke aanroep een nieuw element op. Dit verbetert de prestaties, maar is niet goed voor dynamisch veranderende elementen.
  • searchButton heeft 2 searchButton en geen ID, daarom kan ik geen klassenaam of id gebruiken.
  • Ik heb geverifieerd dat mijn locators me het element geven dat ik wil gebruiken met Developer Tools (voor Chrome), in andere browsers kun je FireBug of iets dergelijks gebruiken.
  • Search() methode Search() retourneert een ander pagina-object ( ResultsPage ) als de klik op de zoekopdracht u naar een andere pagina leidt.

Best Practices Page Object Model

  • Maak afzonderlijke bestanden voor kop- en voettekst (aangezien ze gemeenschappelijk zijn voor alle pagina's en het geen zin heeft om ze deel te laten uitmaken van een enkele pagina)
  • Houd gemeenschappelijke elementen (zoals zoeken / terug / volgende enz.) In een afzonderlijk bestand (het idee is om elke vorm van duplicatie te verwijderen en de segregatie logisch te houden)
  • Voor Driver is het een goed idee om een aparte stuurprogrammaklasse te maken en stuurprogramma zo statisch te houden dat het op alle pagina's toegankelijk is! (Ik heb al mijn webpagina's DriverClass uitbreiden)
  • De functies die in PageObjects worden gebruikt, zijn opgesplitst in kleinst mogelijke brok, rekening houdend met de frequentie en de manier waarop ze worden aangeroepen (de manier waarop u hebt ingelogd, hoewel inloggen kan worden onderverdeeld in enterUsername- en enterPassword-functies maar toch behouden omdat de aanmeldingsfunctie logischer is omdat in de meeste gevallen de aanmeldingsfunctie wordt aangeroepen in plaats van afzonderlijke aanroepen van de functies enterUsername en enterPassword)
  • Het gebruik van PageObjects zelf scheidt het testscript van de elementLocators
  • Heb hulpprogramma functies in aparte map utils (zoals DateUtil, excelUtils etc)
  • Configuraties hebben in een aparte conf-map (zoals het instellen van de omgeving waarin de tests moeten worden uitgevoerd, het configureren van de uitvoer- en invoermappen)
  • Neem screenCapture op bij mislukking
  • Gebruik een statische wachtvariabele in de DriverClass met wat impliciete wachttijd zoals u altijd hebt gedaan Probeer altijd voorwaardelijke wachttijden te hebben in plaats van statische wachttijden zoals: wait.until (ExpectedConditions). Dit zorgt ervoor dat het wachten de uitvoering niet onnodig vertraagt.


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow