selenium-webdriver
Sidobjektmodell
Sök…
Introduktion
By
klassen. Dessa lokaliseringar och interaktioner placeras i sidobjekt som en bästa praxis för att undvika duplikatkod och underlätta underhåll. Det inkapslar WebElements
och antar att innehålla beteende och returnera information på sidan (eller del av en sida i en webbapp).
Anmärkningar
Sidobjektmodell är ett mönster där vi skriver objektorienterade klasser som fungerar som gränssnitt till en viss vy av webbsidan. Vi använder metoderna för den sidklassen för att utföra den nödvändiga åtgärden. För några år tillbaka manipulerade vi HTML-koden på webbsidan i testklasser direkt, vilket var mycket svårt att underhålla tillsammans med sprött förändringar i UI.
Att ha din kod organiserad på ett sätt med Sidobjektmönster ger ett applikationsspecifikt API, så att du kan manipulera sidelementen utan att gräva runt HTML-koden. Den grundläggande tummen säger att ditt sidobjekt bör ha allt som en människa kan göra på den webbsidan. Till exempel för att få tillgång till textfältet på en webbsida bör du använda en metod där för att få texten och returnera strängen efter att ha gjort alla ändringar.
Några viktiga punkter du bör tänka på när du utformar sidobjekten:
Sidobjekt bör vanligtvis inte bygga bara för sidor, men du bör föredra att bygga det för betydande sidelement. Till exempel bör en sida med flera flikar för att visa olika diagram för dina akademiker ha samma antal sidor som antalet flikar.
Navigering från en vy till en annan bör returnera förekomsten av sidklasser.
De verktygsmetoder som krävs för att vara där endast för en viss vy eller webbsida bör endast tillhöra den sidklassen.
Påståendemetoderna bör inte tas om hand av sidklasser, du kan ha metoder för att returnera booleska men verifiera dem inte där. För att verifiera användarens fullständiga namn kan du till exempel ha metod för att få booleskt värde:
public boolean hasDisplayedUserFullName (String userFullName) { return driver.findElement(By.xpath("xpathExpressionUsingFullName")).isDisplayed(); }
Om din webbsida är baserad på iframe, föredrar du att ha sidklasser för iframes också.
Fördelar med sidobjektmönster:
- Rengör skillnaden mellan testkod och sidkod
- I händelse av ändringar i UI: s webbsida behöver du inte ändra din kod på flera platser. Ändra endast i sidklasser.
- Inga spridda element locators.
- Gör koden lättare att förstå
- Enkelt underhåll
Introduktion (med Java)
Ett exempel för att utföra inloggningstest baserat på sidobjektmönster:
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 #
Sidaobjekt bör innehålla beteende, returnera information för påståenden och eventuellt en metod för sidklart tillståndsmetod vid initialisering. Selenium stöder sidobjekt med anteckningar. I C # är det följande:
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;
}
}
anmärkningar:
-
CacheLookup
sparar elementet i cachen och sparar att returnera ett nytt element varje samtal. Detta förbättrar prestanda men är inte bra för att dynamiskt ändra element. -
searchButton
har 2searchButton
och inget ID, det är därför jag inte kan använda klassnamn eller id. - Jag bekräftade att mina lokaliseringar kommer att returnera mig det element jag vill använda utvecklarverktyg (för Chrome), i andra webbläsare kan du använda FireBug eller liknande.
- Metoden
Search()
returnerar ett annat sidobjekt (ResultsPage
) när sökklicket omdirigerar dig till en annan sida.
Bästa metoder Sidobjektmodell
- Skapa separata filer för sidhuvud och sidfot (eftersom de är vanliga för alla sidor och det är inte vettigt att göra dem till en del av en enda sida)
- Förvara vanliga element (som Sök / Tillbaka / Nästa osv) i en separat fil (tanken är att ta bort alla typer av duplikeringar och hålla segregeringen logisk)
- För Driver är det en bra idé att skapa en separat Driver-klass och hålla Driver så statisk så att den kan nås över alla sidor! (Jag har alla mina webbsidor utökade DriverClass)
- Funktionerna som används i PageObjects är indelade i minsta möjliga del, med tanke på frekvensen och hur de kommer att kallas (Det sätt du har gjort för inloggning - även om inloggning kan delas upp i enterUsername och enterPassword-funktioner men fortfarande behåller det eftersom inloggningsfunktionen är mer logisk eftersom i de flesta fall kommer inloggningsfunktionen att kallas snarare än separata samtal till enterUsername och enterPassword-funktioner)
- Att använda PageObjects själv segregerar testskriptet från elementLocators
- Har verktygsfunktioner i separat utils-mapp (som DateUtil, excelUtils etc)
- Ha konfigurationer i separat konfigurationsmapp (som att ställa in den miljö som testerna måste köras på, konfigurera utgångs- och inmatningsmappar)
- Inkorporera screenCapture vid fel
- Ha en statisk väntavariabel i DriverClass med viss implicit väntetid som du har gjort Försök alltid att ha villkorade väntningar snarare än statiska väntningar som: wait.until (ExpectedConditions). Detta säkerställer att väntan inte bromsar exekveringen onödigt.