Automatizare în Selenium: Modelul de obiecte de pagină și Fabrica de pagini

Publicat: 2022-03-11

Scrierea de teste automate este mai mult decât un lux pentru orice echipă agilă de dezvoltare de software. Este o nevoie și este un instrument esențial pentru a găsi rapid erori în fazele incipiente ale ciclurilor de dezvoltare a software-ului. Când există o funcție nouă care este încă în faza de dezvoltare, dezvoltatorii pot rula teste automate și pot vedea cum alte părți ale sistemului sunt afectate de aceste modificări. Acest articol va explica cum puteți accelera testarea automată folosind modelul Page Object în Selenium.

Prin automatizarea testelor, este posibil să reduceți costul remedierii erorilor și să aduceți îmbunătățiri generale procesului de asigurare a calității software (QA). Cu teste adecvate, dezvoltatorii au șansa de a găsi și rezolva erori chiar înainte de a ajunge la QA. Automatizarea testelor ne ajută în continuare să automatizăm cazurile de testare și funcțiile care regresează în mod constant. În acest fel, QA-urile au mai mult timp să testeze alte părți ale aplicației. În plus, acest lucru ajută la asigurarea calității produsului în lansările de producție. Ca rezultat, obținem produse care sunt efectiv mai stabile și un proces de QA care este mai eficient.

Automatizarea cu seleniu simplifică automatizarea testelor pentru aplicațiile web

Selenium simplifică automatizarea testelor pentru aplicațiile web
Tweet

Deși scrierea de teste automate poate părea o sarcină ușoară pentru dezvoltatori și ingineri, există totuși posibilitatea de a ajunge la teste prost implementate și costul ridicat de întreținere a codului în orice proces agil. Încercarea de a furniza în mod constant modificări sau caracteristici în orice proiect de dezvoltare agilă se poate dovedi a fi costisitoare atunci când sunt implicate teste. Schimbarea unui element pe o pagină web pe care se bazează 20 de teste va necesita ca unul să treacă prin aceste 20 de rutine de testare și să le actualizeze pe fiecare pentru a se adapta la această schimbare recent introdusă. Acest lucru nu numai că poate consuma foarte mult timp, ci și un factor serios de demotivare atunci când vine vorba de implementarea testelor automate de la început.

Dar, ce se întâmplă dacă am putea face schimbarea doar într-un singur loc și am putea folosi fiecare rutină de testare relevantă? În acest articol, vom arunca o privire la testele automate în Selenium și la modul în care putem folosi modelele Page Object pentru a scrie rutine de testare care pot fi întreținute și reutilizabile.

Model de obiecte de pagină în seleniu

Modelul de obiecte de pagină este un model de design de obiecte în Selenium, în care paginile web sunt reprezentate ca clase, iar diferitele elemente de pe pagină sunt definite ca variabile ale clasei. Toate interacțiunile posibile ale utilizatorului pot fi apoi implementate ca metode pe clasă:

 clickLoginButton(); setCredentials(user_name,user_password);

Deoarece metodele bine numite din clase sunt ușor de citit, aceasta funcționează ca o modalitate elegantă de a implementa rutine de testare care sunt atât lizibile, cât și mai ușor de întreținut sau actualizat în viitor. De exemplu:

Pentru a sprijini modelul Page Object, folosim Page Factory. Page Factory în Selenium este o extensie a Page Object și poate fi folosită în diferite moduri. În acest caz, vom folosi Page Factory pentru a inițializa elemente web care sunt definite în clase de pagini web sau în obiecte de pagină.

Clasele de pagini web sau obiectele de pagină care conțin elemente web trebuie inițializate folosind Page Factory înainte ca variabilele elementului web să poată fi utilizate. Acest lucru se poate face pur și simplu prin utilizarea funcției initElements pe PageFactory:

 LoginPage page = new LoginPage(driver); PageFactory.initElements(driver, page);

Sau, și mai simplu:

 LoginPage page = PageFactory.intElements(driver,LoginPage.class)

Sau, în interiorul constructorului clasei paginii web:

 public LoginPage(WebDriver driver) { this.driver = driver; PageFactory.initElements(driver, this); }

Page Factory va inițializa fiecare variabilă WebElement cu o referință la un element corespunzător pe pagina web reală pe baza „locatorilor” configurați. Acest lucru se realizează prin utilizarea adnotărilor @FindBy . Cu această adnotare, putem defini o strategie de căutare a elementului, împreună cu informațiile necesare identificării acestuia:

 @FindBy(how=How.NAME, using="username") private WebElement user_name;

De fiecare dată când o metodă este apelată pe această variabilă WebElement , driverul o va găsi mai întâi pe pagina curentă și apoi va simula interacțiunea. În cazul în care lucrăm cu o pagină simplă, știm că vom găsi elementul pe pagină de fiecare dată când îl căutăm și, de asemenea, știm că în cele din urmă vom naviga departe de această pagină și nu vom reveni la ea, putem să punem în cache. câmpul căutat folosind o altă adnotare simplă:

 @FindBy(how=How.NAME, using="username") @CacheLookup private WebElement user_name;

Întreaga definiție a variabilei WebElement poate fi înlocuită cu forma sa mult mai concisă:

 @FindBy(name="username") private WebElement user_name;

Adnotarea @FindBy acceptă o serie de alte strategii care fac lucrurile puțin mai ușoare:

 id, name, className, css, tagName, linkText, partialLinkText, xpath
 @FindBy() private WebElement user_name; @FindBy(name="passsword") private WebElement user_password; @FindBy(className="h3") private WebElement label; @FindBy(css=”#content”) private WebElement text;

Odată inițializate, aceste variabile WebElement pot fi apoi utilizate pentru a interacționa cu elementele corespunzătoare din pagină. Următorul cod va, de exemplu:

 user_password.sendKeys(password);

… trimiteți secvența dată de apăsări de taste în câmpul de parolă de pe pagină și este echivalent cu:

 driver.findElement(By.name(“user_password”)).sendKeys(password);

Mergând mai departe, veți întâlni adesea situații în care trebuie să găsiți o listă de elemente pe o pagină și atunci @FindBys vă este util:

 @FindBys(@FindBy(css=”div[class='yt-lockup-tile yt-lockup-video']”))) private List<WebElement> videoElements;

Codul de mai sus va găsi toate elementele div având două nume de clasă „yt-lockup-tile” și „yt-lockup-video”. Putem simplifica acest lucru și mai mult înlocuindu-l cu următoarele:

 @FindBy(how=How.CSS,using="div[class='yt-lockup-tile yt-lockup-video']") private List<WebElement> videoElements;

În plus, puteți utiliza @FindAll cu mai multe adnotări @FindBy pentru a căuta elemente care se potrivesc cu oricare dintre locatorii dați:

 @FindAll({@FindBy(how=How.ID, using=”username”), @FindBy(className=”username-field”)}) private WebElement user_name;

Acum că putem reprezenta paginile web ca clase Java și folosim Page Factory pentru a inițializa cu ușurință variabilele WebElement , este timpul să vedem cum putem scrie teste Selenium simple folosind modelul Page Object și Page Factory.

Proiect simplu de automatizare a testării seleniului în Java

Pentru tutorialul nostru pentru modelul de obiecte de pagină, să automatizăm înscrierea dezvoltatorilor la Toptal. Pentru a face acest lucru, trebuie să automatizăm următorii pași:

  • Vizitați www.toptal.com

  • Faceți clic pe butonul „Aplicați ca dezvoltator”.

  • Pe pagina portalului verificați mai întâi dacă este deschis

  • Faceți clic pe butonul „Alăturați-vă Toptal”.

  • Completează formularul

  • Trimiteți formularul făcând clic pe butonul „Alăturați-vă Toptal”.

Configurarea unui proiect

  • Descărcați și instalați Java JDK

  • Descărcați și instalați InteliJ Idea

  • Creați un nou proiect Maven

  • Conectați „Project SDK” la JDK-ul dvs., de exemplu: pe Windows „C:\Program Files\Java\jdkxxx”

  • Configurați groupId și artefactId:

 <groupId>SeleniumTEST</groupId> <artifactId>Test</artifactId>
  • Adăugați dependențe Selenium și JUnit Maven în fișierul POM al proiectului
 <dependencies> <!-- JUnit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <!-- Selenium --> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-firefox-driver</artifactId> <version>${selenium.version}</version> </dependency> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-support</artifactId> <version>${selenium.version}</version> </dependency> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>${selenium.version}</version> </dependency> </dependencies>

Înlocuiți versiunea Selenium și versiunea JUnit cu cele mai recente numere de versiune care pot fi găsite căutând JUnit Maven pe Google și pe site-ul Selenium.

În acest moment, dacă construirea automată este activată, dependențele ar trebui să înceapă descărcarea automată. Dacă nu, doar activați Plugins > install > install:install sub panoul Maven Projects din partea dreaptă a IntelliJ Idea IDE.

Captură de ecran IDE tutorial pentru testarea seleniului

Odată ce proiectul a fost bootstrap, putem începe să creăm pachetul nostru de testare sub „src/test/java”. Denumiți pachetul „com.toptal” și creați încă două pachete sub el: „com.toptal.webpages” și „com.toptal.tests”.

captură de ecran tutorial pentru testarea seleniului

Vom păstra clasele Page Object/Page Factory sub „com.toptal.webpages” și rutinele de testare sub „com.toptal.tests”.

Acum, putem începe să ne creăm clasele Page Object.

Obiect de pagină de pornire

Prima pe care trebuie să o implementăm este pentru pagina de pornire a Toptal (www.toptal.com). Creați o clasă sub „com.toptal.webpages” și denumiți-o „HomePage”.

 package com.toptal.webpages; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.How; import org.openqa.selenium.support.PageFactory; public class HomePage { private WebDriver driver; //Page URL private static String PAGE_URL="https://www.toptal.com"; //Locators //Apply as Developer Button @FindBy(how = How.LINK_TEXT, using = "APPLY AS A DEVELOPER") private WebElement developerApplyButton; //Constructor public HomePage(WebDriver driver){ this.driver=driver; driver.get(PAGE_URL); //Initialise Elements PageFactory.initElements(driver, this); } public void clickOnDeveloperApplyButton(){ developerApplyButton.click(); } }

Determinarea localizatorilor de elemente

Pe pagina de start a Toptal suntem interesați de un element în special și acesta este butonul „Aplicați ca dezvoltator”. Putem găsi acest element prin potrivirea textului, ceea ce facem mai sus. În timp ce modelați pagini web ca clase de obiecte de pagină, găsirea și identificarea elementelor poate deveni adesea o corvoadă. Cu instrumentele de depanare ale Google Chrome sau Firefox, acest lucru poate fi simplificat. Făcând clic dreapta pe orice element dintr-o pagină, puteți activa opțiunea „Inspectați elementul” din meniul contextual pentru a afla informații detaliate despre element.

O modalitate obișnuită (și preferata mea) este de a găsi elemente folosind extensia FireBug a Firefox, în combinație cu driverul web Firefox din Selenium. După instalarea și activarea extensiei FireBug, puteți face clic dreapta pe pagină și selectați „Inspectați elementul cu FireBug” pentru a deschide FireBug. Din fila HTML a FireBug, puteți copia XPath, Calea CSS, numele etichetei sau „Id” (dacă este disponibil) al oricărui element de pe pagină.

model de obiect de pagină în seleniu: localizatori de elemente determinanți

Copiind XPath-ul elementului din captura de ecran de mai sus, putem crea un câmp WebElement pentru acesta în obiectul nostru de pagină, după cum urmează:

 @FindBy(xpath = "/html/body/div[1]/div/div/header/div/h1") WebElement heading;

Sau pentru a menține lucrurile simple, putem folosi numele de etichetă „h1” aici, atâta timp cât identifică în mod unic elementul care ne interesează:

 @FindBy(tagName = "h1") WebElement heading;

Obiectul pagină DeveloperPortalPage

În continuare, avem nevoie de un obiect de pagină care reprezintă pagina portalului dezvoltatorului, unul la care putem ajunge făcând clic pe butonul „Aplicați ca dezvoltator”.

Pe această pagină, avem două elemente de interes. Pentru a stabili dacă pagina s-a încărcat, dorim să verificăm existența titlului. Și vrem, de asemenea, un câmp WebElement pentru butonul „Alăturați-vă Toptal”.

 package com.toptal.webpages; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.PageFactory; public class DeveloperPortalPage { private WebDriver driver; @FindBy(xpath = "/html/body/div[1]/div/div/header/div/h1") private WebElement heading; @FindBy(linkText = "JOIN TOPTAL") private WebElement joinToptalButton; //Constructor public DeveloperPortalPage (WebDriver driver){ this.driver=driver; //Initialise Elements PageFactory.initElements(driver, this); } //We will use this boolean for assertion. To check if page is opened public boolean isPageOpened(){ return heading.getText().toString().contains("Developer portal"); } public void clikOnJoin(){ joinToptalButton.click(); } }

Obiectul pagină DeveloperApplyPage

Și, în sfârșit, pentru al treilea și ultimul nostru obiect de pagină pentru acest proiect, definim unul care reprezintă pagina care conține formularul de cerere pentru dezvoltatori. Deoarece aici avem de a face cu un număr de câmpuri de formular, definim o variabilă WebElement pentru fiecare câmp de formular. Găsim fiecare câmp după „id”-ul său și definim metode speciale de setare pentru fiecare câmp care simulează apăsările de taste pentru câmpurile corespunzătoare.

 package com.toptal.webpages; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.PageFactory; public class DeveloperApplyPage { private WebDriver driver; @FindBy(tagName = "h1") WebElement heading; @FindBy() WebElement developer_email; @FindBy() WebElement developer_password; @FindBy() WebElement developer_password_confirmation; @FindBy() WebElement developer_full_name; @FindBy() WebElement developer_skype; @FindBy() WebElement join_toptal_button; //Constructor public DeveloperApplyPage(WebDriver driver){ this.driver=driver; //Initialise Elements PageFactory.initElements(driver, this); } public void setDeveloper_email(String email){ developer_email.clear(); developer_email.sendKeys(email); } public void setDeveloper_password(String password){ developer_password.clear(); developer_password.sendKeys(password); } public void setDeveloper_password_confirmation(String password_confirmation){ developer_password_confirmation.clear(); developer_password_confirmation.sendKeys(password_confirmation); } public void setDeveloper_full_name (String fullname){ developer_full_name.clear(); developer_full_name.sendKeys(fullname); } public void setDeveloper_skype (String skype){ developer_skype.clear(); developer_skype.sendKeys(skype); } public void clickOnJoin(){ join_toptal_button.click(); } public boolean isPageOpened(){ //Assertion return heading.getText().toString().contains("Apply to join our network as a developer"); } }

Scrierea unui test simplu de seleniu

Cu clasele Page Object reprezentând paginile noastre și interacțiunile utilizatorilor ca metode ale acestora, acum putem scrie rutina noastră simplă de testare ca o serie de apeluri și afirmații simple de metodă.

 package com.toptal.tests; import com.toptal.webpages.DeveloperApplyPage; import com.toptal.webpages.DeveloperPortalPage; import com.toptal.webpages.HomePage; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; import java.net.URL; import java.util.concurrent.TimeUnit; public class ApplyAsDeveloperTest { WebDriver driver; @Before public void setup(){ //use FF Driver driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); } @Test public void applyAsDeveloper() { //Create object of HomePage Class HomePage home = new HomePage(driver); home.clickOnDeveloperApplyButton(); //Create object of DeveloperPortalPage DeveloperPortalPage devportal= new DeveloperPortalPage(driver); //Check if page is opened Assert.assertTrue(devportal.isPageOpened()); //Click on Join Toptal devportal.clikOnJoin(); //Create object of DeveloperApplyPage DeveloperApplyPage applyPage =new DeveloperApplyPage(driver); //Check if page is opened Assert.assertTrue(applyPage.isPageOpened()); //Fill up data applyPage.setDeveloper_email("[email protected]"); applyPage.setDeveloper_full_name("Dejan Zivanovic Automated Test"); applyPage.setDeveloper_password("password123"); applyPage.setDeveloper_password_confirmation("password123"); applyPage.setDeveloper_skype("automated_test_skype"); //Click on join //applyPage.clickOnJoin(); } @After public void close(){ driver.close(); } }

Executarea testului

În acest moment, structura proiectului dumneavoastră ar trebui să arate astfel:

exemplu de testare a seleniului

Dacă doriți să rulați testul, selectați „ApplyAsDeveloperTest” din arbore, faceți clic dreapta pe el și apoi selectați Run „ApplyAsDeveloperTest” .

exemplu de testare a seleniului

Odată ce testul a fost rulat, puteți vedea rezultatele în colțul din stânga jos al IDE-ului dvs.:

exemplu de testare a seleniului

Concluzie

Page Object și Page Factory facilitează modelarea paginilor web în Selenium și testarea lor automată și simplifică mult viața atât a dezvoltatorilor, cât și a QA. Când sunt făcute corect, aceste clase de obiecte de pagină pot fi reutilizate în întreaga suită de teste și pentru a vă oferi oportunitatea de a implementa teste Selenium automate pentru proiectele dvs. de la început, fără a compromite dezvoltarea agilă. Abstragând interacțiunile utilizatorilor din modelele de obiecte ale paginii și menținând rutinele de testare ușoare și simple, vă puteți adapta suita de teste la cerințele în schimbare cu puțin efort.

Sper că am reușit să vă arăt cum să scrieți un cod de test frumos și curat, care este ușor de întreținut. Voi încheia articolul cu citatul meu preferat QA:

Gândește-te de două ori, codifică o dată!

Înrudit: Web Scraping cu un browser fără cap: Un tutorial pentru păpuși