Modello di oggetti di pagina e fabbrica in Selenium
Che cos'è il modello a oggetti di pagina?
Modello oggetto pagina (POM) è un modello di progettazione, comunemente utilizzato nell'automazione dei test, che crea un repository di oggetti per elementi dell'interfaccia utente Web. Il vantaggio del modello è che riduce la duplicazione del codice e migliora la manutenzione dei test.
Secondo questo modello, per ogni pagina web nell'applicazione, dovrebbe esserci una classe di pagina corrispondente. Questa classe Page identificherà i WebElements di quella pagina web e contiene anche i metodi Page che eseguono operazioni su tali WebElements. Il nome di questi metodi deve essere fornito in base all'attività che stanno eseguendo, ovvero, se un caricatore è in attesa che venga visualizzato il gateway di pagamento, il nome del metodo POM può essere waitForPaymentScreenDisplay().
Perché il modello a oggetti della pagina?
Avvio di un'automazione dell'interfaccia utente in Selenium WebDriver NON è un compito difficile. Hai solo bisogno di trovare elementi, eseguire operazioni su di essi.
Considera questo semplice script per accedere a un sito web
Come puoi osservare, tutto ciò che stiamo facendo è trovare elementi e riempire valori per tali elementi.
Questa è una piccola sceneggiatura. La manutenzione degli script sembra semplice. Ma con il tempo la suite di test crescerà. Man mano che aggiungi sempre più righe al tuo codice, le cose diventano difficili.
Il problema principale con la manutenzione degli script è che se 10 script diversi utilizzano lo stesso elemento della pagina, con qualsiasi modifica in quell'elemento, è necessario modificare tutti e 10 gli script. Ciò richiede tempo ed è soggetto a errori.
Un approccio migliore alla manutenzione degli script è creare un file di classe separato che trovi gli elementi web, li riempia o li verifichi. Questa classe può essere riutilizzata in tutti gli script che utilizzano quell'elemento. In futuro, se si verifica una modifica nell'elemento web, dovremo apportare la modifica solo in 1 file di classe e non in 10 script diversi.
Questo approccio è chiamato Page Object Model in Selenium. Aiuta a rendere il codice più leggibile, manutenibile e riutilizzabile.
Vantaggi del POM
- Page Object Design Pattern afferma che le operazioni e i flussi nell'interfaccia utente dovrebbero essere separati dalla verifica. Questo concetto rende il nostro codice più pulito e facile da capire.
- Il secondo vantaggio è che il repository di oggetti è indipendente dai casi di test, quindi possiamo utilizzare lo stesso repository di oggetti per uno scopo diverso con strumenti diversi. Ad esempio, possiamo integrare il Page Object Model in Selenium con TestNG/JUnit per funzionale Testing e allo stesso tempo con JBehave/Cucumber per le prove di accettazione.
- Il codice diventa meno numeroso e ottimizzato grazie ai metodi di pagina riutilizzabili nelle classi POM.
- I metodi ottengono nomi più realistici che possono essere facilmente mappati con l'operazione che avviene nell'interfaccia utente. cioè se dopo aver cliccato sul pulsante arriviamo alla home page, il nome del metodo sarà come 'gotoHomePage()'.
Come implementare il POM?
POM semplice:
È la struttura di base del framework del modello a oggetti di pagina in cui tutti gli elementi Web del file funzione AUT e il metodo che opera su questi elementi Web vengono mantenuti all'interno di un file di classe. Un'attività come la verifica dovrebbe essere separata come parte dei metodi di test.
Esempio completo
Caso di prova: Vai al sito dimostrativo di Guru99.
Passaggio 1) Vai al sito demo di Guru99
Passaggio 2) Nella home page verificare che sia presente il testo "Guru99 Bank".
Passaggio 3) Accedi all'applicazione
Passaggio 4) Verifica che la home page contenga il testo "ID manager: demo"
Qui abbiamo a che fare con 2 pagine
- Pagina di login
- Home Page (mostrata una volta effettuato l'accesso)
Di conseguenza, creiamo 2 POM in Selenium classi
Guru99 Pagina di accesso POM
package pages; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; public class Guru99Login { WebDriver driver; By user99GuruName = By.name("uid"); By password99Guru = By.name("password"); By titleText =By.className("barone"); By login = By.name("btnLogin"); public Guru99Login(WebDriver driver){ this.driver = driver; } //Set user name in textbox public void setUserName(String strUserName){ driver.findElement(user99GuruName).sendKeys(strUserName); } //Set password in password textbox public void setPassword(String strPassword){ driver.findElement(password99Guru).sendKeys(strPassword); } //Click on login button public void clickLogin(){ driver.findElement(login).click(); } //Get the title of Login Page public String getLoginTitle(){ return driver.findElement(titleText).getText(); } /** * This POM method will be exposed in test case to login in the application * @param strUserName * @param strPasword * @return */ public void loginToGuru99(String strUserName,String strPasword){ //Fill user name this.setUserName(strUserName); //Fill password this.setPassword(strPasword); //Click Login button this.clickLogin(); } }
Guru99 Home Page POM in Selenium
package pages; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; public class Guru99HomePage { WebDriver driver; By homePageUserName = By.xpath("//table//tr[@class='heading3']"); public Guru99HomePage(WebDriver driver){ this.driver = driver; } //Get the User name from Home Page public String getHomePageDashboardUserName(){ return driver.findElement(homePageUserName).getText(); } }
Guru99 POM semplice in Selenium Caso di prova
package test; import java.util.concurrent.TimeUnit; import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.testng.Assert; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import pages.Guru99HomePage; import pages.Guru99Login; public class Test99GuruLogin { String driverPath = "C:\\geckodriver.exe"; WebDriver driver; Guru99Login objLogin; Guru99HomePage objHomePage; @BeforeTest public void setup(){ System.setProperty("webdriver.gecko.driver", driverPath); driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.get("https://demo.guru99.com/V4/"); } /** * This test case will login in https://demo.guru99.com/V4/ * Verify login page title as guru99 bank * Login to application * Verify the home page using Dashboard message */ @Test(priority=0) public void test_Home_Page_Appear_Correct(){ //Create Login Page object objLogin = new Guru99Login(driver); //Verify login page title String loginPageTitle = objLogin.getLoginTitle(); Assert.assertTrue(loginPageTitle.toLowerCase().contains("guru99 bank")); //login to application objLogin.loginToGuru99("mgr123", "mgr!23"); // go the next page objHomePage = new Guru99HomePage(driver); //Verify home page Assert.assertTrue(objHomePage.getHomePageDashboardUserName().toLowerCase().contains("manger id : mgr123")); }
In cosa consiste Page Factory Selenium?
Pagina Fabbrica in Selenium è un concetto di framework Page Object Model integrato per Selenium WebDriver ma è molto ottimizzato. Viene utilizzato per l'inizializzazione degli oggetti Page o per creare un'istanza dell'oggetto Page stesso. Viene utilizzato anche per inizializzare gli elementi della classe Page senza utilizzare "FindElement/s".
Anche qui seguiamo il concetto di separazione tra Page Object Repository e Test Methods. Inoltre, con l'aiuto della classe PageFactory in Selenium, usiamo le annotazioni @FindBy per trovare WebElement. Usiamo il metodo initElements per inizializzare gli elementi web
@FindBy può accettare tagName, partialLinkText, nome, linkText, id, css, className, xpath come attributi.
Diamo un'occhiata allo stesso esempio di cui sopra utilizzando Page Factory
Pagina di accesso di Guru99 con Page Factory
package PageFactory; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.PageFactory; public class Guru99Login { /** * All WebElements are identified by @FindBy annotation */ WebDriver driver; @FindBy(name="uid") WebElement user99GuruName; @FindBy(name="password") WebElement password99Guru; @FindBy(className="barone") WebElement titleText; @FindBy(name="btnLogin") WebElement login; public Guru99Login(WebDriver driver){ this.driver = driver; //This initElements method will create all WebElements PageFactory.initElements(driver, this); } //Set user name in textbox public void setUserName(String strUserName){ user99GuruName.sendKeys(strUserName); } //Set password in password textbox public void setPassword(String strPassword){ password99Guru.sendKeys(strPassword); } //Click on login button public void clickLogin(){ login.click(); } //Get the title of Login Page public String getLoginTitle(){ return titleText.getText(); } /** * This POM method will be exposed in test case to login in the application * @param strUserName * @param strPasword * @return */ public void loginToGuru99(String strUserName,String strPasword){ //Fill user name this.setUserName(strUserName); //Fill password this.setPassword(strPasword); //Click Login button this.clickLogin(); } }
Home page di Guru99 con Page Factory
package PageFactory; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.PageFactory; public class Guru99HomePage { WebDriver driver; @FindBy(xpath="//table//tr[@class='heading3']") WebElement homePageUserName; public Guru99HomePage(WebDriver driver){ this.driver = driver; //This initElements method will create all WebElements PageFactory.initElements(driver, this); } //Get the User name from Home Page public String getHomePageDashboardUserName(){ return homePageUserName.getText(); } }
Guru99 TestCase con il concetto di Page Factory
package test; import java.util.concurrent.TimeUnit; import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.testng.Assert; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import PageFactory.Guru99HomePage; import PageFactory.Guru99Login; public class Test99GuruLoginWithPageFactory { String driverPath = "C:\\geckodriver.exe"; WebDriver driver; Guru99Login objLogin; Guru99HomePage objHomePage; @BeforeTest public void setup(){ System.setProperty("webdriver.gecko.driver", driverPath); driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.get("https://demo.guru99.com/V4/"); } /** * This test go to https://demo.guru99.com/V4/ * Verify login page title as guru99 bank * Login to application * Verify the home page using Dashboard message */ @Test(priority=0) public void test_Home_Page_Appear_Correct(){ //Create Login Page object objLogin = new Guru99Login(driver); //Verify login page title String loginPageTitle = objLogin.getLoginTitle(); Assert.assertTrue(loginPageTitle.toLowerCase().contains("guru99 bank")); //login to application objLogin.loginToGuru99("mgr123", "mgr!23"); // go the next page objHomePage = new Guru99HomePage(driver); //Verify home page Assert.assertTrue(objHomePage.getHomePageDashboardUserName().toLowerCase().contains("manger id : mgr123")); } }
La struttura completa del progetto sarà simile al diagramma:
AjaxElementLocatorFactory
AjaxElementLocatorFactory è un concetto di caricamento lento di PageFactory in Selenium. Viene utilizzato per trovare gli elementi web solo quando gli elementi vengono utilizzati in qualsiasi operazione. Assegna un timeout per WebElements alla classe della pagina dell'oggetto. Uno dei principali vantaggi dell'utilizzo del pattern PageFactory in Selenium è la classe AjaxElementLocatorFactory.
Ecco che quando viene eseguita un'operazione su un elemento l'attesa per la sua visibilità inizia solo da quel momento. Se l'elemento non viene trovato nell'intervallo di tempo specificato, Test Case l'esecuzione genererà l'eccezione "NoSuchElementException".
Sommario
- Modello oggetto pagina in Selenium WebDriver è un modello di progettazione di repository di oggetti.
- Selenium il modello a oggetti della pagina crea il nostro codice di test manutenibile, riutilizzabile.
- Page Factory è un modo ottimizzato per creare repository di oggetti nel concetto di framework Page Object Model.
- AjaxElementLocatorFactory è un concetto di caricamento lento in Page Factory: modello di progettazione di oggetti di pagina per identificare WebElements solo quando vengono utilizzati in qualsiasi operazione.
Scarica la Selenium File di progetto per la demo in questo tutorial