page object model with page factory selenium tutorial
Este tutorial detalhado explica tudo sobre o modelo de objeto de página (POM) com o Pagefactory usando exemplos. Você também pode aprender a implementação do POM no Selenium:
Neste tutorial, entenderemos como criar um Modelo de Objeto de Página usando a abordagem de Fábrica de Página. Vamos nos concentrar em:
- Classe de Fábrica
- Como criar um POM básico usando o padrão de fábrica de página
- Diferentes anotações usadas na abordagem de fábrica de página
Antes de ver o que é Pagefactory e como ele pode ser usado junto com o modelo de objeto de Página, vamos entender o que é Modelo de Objeto de Página, comumente conhecido como POM.
=> Visite aqui para ver a série de treinamento Selenium For All.
O que você aprenderá:
- O que é o modelo de objeto de página (POM)?
- O que é Pagefactory?
- POM usando o Page Factory
- perguntas frequentes
- Conclusão
O que é o modelo de objeto de página (POM)?
Terminologias teóricas descrevem o Modelo de objeto de página como um padrão de design usado para construir um repositório de objetos para os elementos da web disponíveis no aplicativo em teste. Poucos outros se referem a ele como uma estrutura para automação do Selenium para o aplicativo em teste.
No entanto, o que entendi sobre o termo Modelo de objeto de página é:
# 1) É um padrão de design em que você tem um arquivo de classe Java separado correspondente a cada tela ou página no aplicativo. O arquivo de classe pode incluir o repositório de objetos dos elementos da interface do usuário, bem como métodos.
#dois) No caso de haver enormes elementos da web em uma página, a classe do repositório de objetos para uma página pode ser separada da classe que inclui métodos para a página correspondente.
Exemplo: Se a página Registrar conta tiver muitos campos de entrada, pode haver uma classe RegisterAccountObjects.java que forma o repositório de objetos para os elementos da interface do usuário na página registrar contas.
Um arquivo de classe separado RegisterAccount.java estendendo ou herdando RegisterAccountObjects que inclui todos os métodos que executam diferentes ações na página pode ser criado.
# 3) Além disso, pode haver um pacote genérico com um arquivo {roperties, dados de teste do Excel e métodos comuns em um pacote.
Exemplo: DriverFactory que pode ser usado facilmente em todas as páginas do aplicativo
Compreendendo o POM com o exemplo
Verificar aqui para saber mais sobre o POM.
Abaixo está um instantâneo da página da web:
Clicar em cada um desses links redirecionará o usuário para uma nova página.
Aqui está um instantâneo de como a estrutura do projeto com Selenium é construída usando o modelo de objeto Página correspondente a cada página do site. Cada classe Java inclui repositório de objetos e métodos para executar diferentes ações na página.
Além disso, haverá outro JUNIT ou TestNG ou um arquivo de classe Java invocando chamadas para arquivos de classe dessas páginas.
Por que usamos o modelo de objeto de página?
Há um burburinho sobre o uso desta poderosa estrutura Selenium chamada POM ou modelo de objeto de página. Agora, surge a pergunta “Por que usar o POM?”.
A resposta simples para isso é que o POM é uma combinação de estruturas baseadas em dados, modulares e híbridas. É uma abordagem para organizar sistematicamente os scripts de forma que seja fácil para o controle de qualidade manter o código livre de aborrecimentos e também ajuda a evitar código redundante ou duplicado.
Por exemplo, se houver uma alteração no valor do localizador em uma página específica, será muito fácil identificar e fazer essa alteração rápida apenas no script da respectiva página, sem afetar o código em outro lugar.
Usamos o conceito de Modelo de Objeto de Página no Selenium Webdriver devido aos seguintes motivos:
- Um repositório de objetos é criado neste modelo POM. É independente de casos de teste e pode ser reutilizado para um projeto diferente.
- A convenção de nomenclatura de métodos é muito fácil, compreensível e mais realista.
- No modelo de objeto Página, criamos classes de página que podem ser reutilizadas em outro projeto.
- O modelo de objeto Página é fácil para o framework desenvolvido devido às suas diversas vantagens.
- Neste modelo, classes separadas são criadas para diferentes páginas de um aplicativo da web, como página de login, página inicial, página de detalhes do funcionário, página de alteração de senha, etc.
- Se houver alguma alteração em qualquer elemento de um site, precisamos fazer alterações apenas em uma classe, e não em todas as classes.
- O script projetado é mais reutilizável, legível e sustentável na abordagem do modelo de objeto de página.
- Sua estrutura de projeto é bastante fácil e compreensível.
- Pode usar PageFactory no modelo de objeto de página para inicializar o elemento da web e armazenar elementos no cache.
- TestNG também pode ser integrado à abordagem do Modelo de Objeto de Página.
Implementação de POM simples no selênio
# 1) Cenário para automatizar
Agora, automatizamos o cenário fornecido usando o modelo de objeto de página.
O cenário é explicado abaixo:
Passo 1: Abra o site “https: //demo.vtiger.com”.
Passo 2: Insira a credencial válida.
Etapa 3: Faça login no site.
Passo 4: Verifique a página inicial.
Etapa 5: Saia do site.
Etapa 6: Feche o navegador.
# 2) Scripts de selênio para o cenário acima no POM
Agora criamos a estrutura POM no Eclipse, conforme explicado abaixo:
Passo 1: Crie um projeto no Eclipse - Estrutura baseada em POM:
a) Crie o projeto “Modelo de objeto de página”.
b) Crie 3 Pacote no projeto.
- biblioteca
- Páginas
- casos de teste
Biblioteca: Sob isso, colocamos os códigos que precisam ser chamados repetidamente em nossos casos de teste, como inicialização do navegador, capturas de tela, etc. O usuário pode adicionar mais classes com base na necessidade do projeto.
Páginas: Com isso, as classes são criadas para cada página no aplicativo da web e podem adicionar mais classes de página com base no número de páginas no aplicativo.
Casos de teste: Sob isso, escrevemos o caso de teste de login e podemos adicionar mais casos de teste conforme necessário para testar todo o aplicativo.
c) As aulas dos Pacotes são mostradas na imagem abaixo.
Etapa dois: Crie as seguintes classes no pacote da biblioteca.
Browser.java: Nesta classe, 3 navegadores (Firefox, Chrome e Internet Explorer) são definidos e chamados no caso de teste de login. Com base no requisito, o usuário também pode testar o aplicativo em diferentes navegadores.
package library; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.ie.InternetExplorerDriver; public class Browser { static WebDriver driver; public static WebDriver StartBrowser(String browsername , String url) { // If the browser is Firefox if (browsername.equalsIgnoreCase('Firefox')) { // Set the path for geckodriver.exe System.setProperty('webdriver.firefox.marionette',' E://Selenium//Selenium_Jars//geckodriver.exe '); driver = new FirefoxDriver(); } // If the browser is Chrome else if (browsername.equalsIgnoreCase('Chrome')) { // Set the path for chromedriver.exe System.setProperty('webdriver.chrome.driver','E://Selenium//Selenium_Jars//chromedriver.exe'); driver = new ChromeDriver(); } // If the browser is IE else if (browsername.equalsIgnoreCase('IE')) { // Set the path for IEdriver.exe System.setProperty('webdriver.ie.driver','E://Selenium//Selenium_Jars//IEDriverServer.exe'); driver = new InternetExplorerDriver(); } driver.manage().window().maximize(); driver.get(url); return driver; } }
ScreenShot.java: Nesta aula, um programa de captura de tela é escrito e chamado no caso de teste quando o usuário deseja fazer uma captura de tela para verificar se o teste foi reprovado ou aprovado.
package library; import java.io.File; import org.apache.commons.io.FileUtils; import org.openqa.selenium.OutputType; import org.openqa.selenium.TakesScreenshot; import org.openqa.selenium.WebDriver; public class ScreenShot { public static void captureScreenShot(WebDriver driver, String ScreenShotName) { try { File screenshot=((TakesScreenshot)driver).getScreenshotAs(OutputType. FILE ); FileUtils.copyFile(screenshot, new File('E://Selenium//'+ScreenShotName+'.jpg')); } catch (Exception e) { System. out .println(e.getMessage()); e.printStackTrace(); } } }
Etapa 3 : Crie classes de página no pacote de página.
HomePage.java: Esta é a classe da página inicial, na qual todos os elementos da página inicial e métodos são definidos.
package pages; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; public class HomePage { WebDriver driver; By logout = By.id('p_lt_ctl03_wSOB_btnSignOutLink'); By home = By.id('p_lt_ctl02_wCU2_lblLabel'); //Constructor to initialize object public HomePage(WebDriver dr) { this .driver=dr; } public String pageverify() { return driver.findElement(home).getText(); } public void logout() { driver.findElement(logout).click(); } }
LoginPage.java: Esta é a classe da página de login, na qual todos os elementos da página de login e métodos são definidos.
package pages; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; public class LoginPage { WebDriver driver; By UserID = By.xpath('//*(contains(@id,'Login1_UserName'))'); By password = By.xpath('//*(contains(@id,'Login1_Password'))'); By Submit = By.xpath('//*(contains(@id,'Login1_LoginButton'))'); //Constructor to initialize object public LoginPage(WebDriver driver) { this .driver = driver; } public void loginToSite(String Username, String Password) { this .enterUsername(Username); this .enterPasssword(Password); this .clickSubmit(); } public void enterUsername(String Username) { driver.findElement(UserID).sendKeys(Username); } public void enterPasssword(String Password) { driver.findElement(password).sendKeys(Password); } public void clickSubmit() { driver.findElement(Submit).click(); } }
Passo 4: Crie casos de teste para o cenário de login.
LoginTestCase.java: Esta é a classe LoginTestCase, onde o caso de teste é executado. O usuário também pode criar mais casos de teste de acordo com a necessidade do projeto.
package testcases; import java.util.concurrent.TimeUnit; import library.Browser; import library.ScreenShot; import org.openqa.selenium.WebDriver; import org.testng.Assert; import org.testng.ITestResult; import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import pages.HomePage; import pages.LoginPage; public class LoginTestCase { WebDriver driver; LoginPage lp; HomePage hp; int i = 0; // Launch of the given browser. @BeforeTest public void browserlaunch() { driver = Browser.StartBrowser('Chrome', 'http://demostore.kenticolab.com/Special-Pages/Logon.aspx'); driver.manage().timeouts().implicitlyWait(30,TimeUnit. SECONDS ); lp = new LoginPage(driver); hp = new HomePage(driver); } // Login to the Site. @Test(priority = 1) public void Login() { lp.loginToSite('gaurav.3n@gmail.com','Test@123'); } // Verifing the Home Page. @Test(priority = 2) public void HomePageVerify() { String HomeText = hp.pageverify(); Assert.assertEquals(HomeText, 'Logged on as'); } // Logout the site. @Test(priority = 3) public void Logout() { hp.logout(); } // Taking Screen shot on test fail @AfterMethod public void screenshot(ITestResult result) { i = i+1; String name = 'ScreenShot'; String x = name+String.valueOf(i); if (ITestResult. FAILURE == result.getStatus()) { ScreenShot.captureScreenShot(driver, x); } } @AfterTest public void closeBrowser() { driver.close(); } }
Etapa 5: Execute “LoginTestCase.java“.
Etapa 6: Saída do modelo de objeto de página:
- Inicie o navegador Chrome.
- O site de demonstração é aberto no navegador.
- Faça login no site de demonstração.
- Verifique a página inicial.
- Saia do site.
- Feche o navegador.
Agora, vamos explorar o conceito principal deste tutorial que chama a atenção, ou seja, “Pagefactory”.
O que é Pagefactory?
PageFactory é uma forma de implementar o “Modelo de Objeto de Página”. Aqui, seguimos o princípio de separação de Repositório de Objetos de Página e Métodos de Teste. É um conceito embutido de Modelo de Objeto de Página que é muito otimizado.
Vamos agora ter mais clareza sobre o termo Pagefactory.
# 1) Em primeiro lugar, o conceito chamado Pagefactory, fornece uma maneira alternativa em termos de sintaxe e semântica para a criação de um repositório de objetos para os elementos da web em uma página.
#dois) Em segundo lugar, ele usa uma estratégia ligeiramente diferente para a inicialização dos elementos da web.
# 3) O repositório de objetos para os elementos da web da interface do usuário pode ser construído usando:
- Usual ‘POM sem Pagefactory’ e,
- Alternativamente, você pode usar ‘POM com Pagefactory’.
Dada a seguir é uma representação pictórica do mesmo:
Agora veremos todos os aspectos que diferenciam o POM usual do POM com Pagefactory.
a) A diferença na sintaxe de localização de um elemento usando o POM usual vs POM com Pagefactory.
Por exemplo , Clique aqui para localizar o campo de pesquisa que aparece na página.
POM sem Pagefactory:
# 1) Abaixo está como você localiza o campo de pesquisa usando o POM usual:
WebElement searchNSETxt=driver.findElement(By.id(“searchBox”));
# 2) A etapa abaixo passa o valor “investimento” para o campo Pesquisar NSE.
searchNSETxt.sendkeys(“investment”);
POM usando Pagefactory:
# 1) Você pode localizar o campo de pesquisa usando o Pagefactory conforme mostrado abaixo.
A anotação @FindBy é usado no Pagefactory para identificar um elemento, enquanto o POM sem o Pagefactory usa o driver.findElement () método para localizar um elemento.
A segunda declaração para Pagefactory após @FindBy está atribuindo um do tipo WebElement classe que funciona exatamente semelhante à atribuição de um nome de elemento do tipo WebElement classe como um tipo de retorno do método driver.findElement () que é usado no POM normal (searchNSETxt neste exemplo).
Vamos olhar para o @FindBy anotações em detalhes na próxima parte deste tutorial.
@FindBy(id = 'searchBox') WebElement searchNSETxt;
#dois) A etapa a seguir passa o valor “investimento” para o campo Pesquisar NSE e a sintaxe permanece a mesma do POM normal (POM sem Pagefactory).
searchNSETxt.sendkeys(“investment”);
b) A diferença na estratégia de inicialização de Web Elements usando o usual POM vs POM com Pagefactory.
Usando POM sem Pagefactory:
Abaixo está um trecho de código para definir o caminho do driver do Chrome. Uma instância do WebDriver é criada com o nome driver e o ChromeDriver é atribuído ao ‘driver’. O mesmo objeto driver é então usado para iniciar o site da National Stock Exchange, localizar o searchBox e inserir o valor da string no campo.
O ponto que desejo destacar aqui é que, quando é POM sem fábrica de página, a instância do driver é criada inicialmente e cada elemento da web é inicializado novamente cada vez que há uma chamada para esse elemento da web usando driver.findElement () ou driver .findElements ().
É por isso que, com uma nova etapa de driver.findElement () para um elemento, a estrutura DOM é novamente examinada e a identificação atualizada do elemento é feita nessa página.
System.setProperty('webdriver.chrome.driver', 'C:\eclipse-workspace\automationframework\src\test\java\Drivers\chromedriver.exe'); WebDriver driver = new ChromeDriver(); driver.get('http://www.nseindia.com/'); WebElement searchNSETxt=driver.findElement(By.id(“searchBox”)); searchNSETxt.sendkeys(“investment”);
Usando POM com Pagefactory:
Além de usar a anotação @FindBy em vez do método driver.findElement (), o trecho de código abaixo é usado adicionalmente para Pagefactory. O método initElements () estático da classe PageFactory é usado para inicializar todos os elementos da interface do usuário na página assim que a página é carregada.
public PagefactoryClass(WebDriver driver) { this.driver = driver; PageFactory.initElements(driver, this); }
A estratégia acima torna a abordagem da PageFactory um pouco diferente do POM usual. No POM usual, o elemento da web deve ser inicializado explicitamente, enquanto na abordagem da Pagefactory todos os elementos são inicializados com initElements () sem inicializar explicitamente cada elemento da web.
Por exemplo: Se o WebElement foi declarado, mas não inicializado no POM usual, o erro “inicializar variável” ou NullPointerException é lançado. Portanto, no POM normal, cada WebElement deve ser inicializado explicitamente. O PageFactory vem com uma vantagem sobre o POM normal neste caso.
Não vamos inicializar o elemento web BDate (POM sem Pagefactory), você pode ver que o erro 'Inicializar variável' é exibido e solicita que o usuário inicialize-o como nulo, portanto, você não pode assumir que os elementos foram inicializados implicitamente ao localizá-los.
Elemento BDate inicializado explicitamente (POM sem Pagefactory):
Agora, vamos dar uma olhada em algumas instâncias de um programa completo usando PageFactory para descartar qualquer ambigüidade na compreensão do aspecto de implementação.
Exemplo 1:
- Vá para ‘http://www.nseindia.com/’
- No menu suspenso ao lado do campo de pesquisa, selecione ‘Derivativos de moeda’.
- Pesquise por ‘USDINR’. Verifique o texto ‘US Dollar-Indian Rupee - USDINR’ na página resultante.
Estrutura do programa:
- PagefactoryClass.java que inclui um repositório de objetos usando o conceito de fábrica de páginas para nseindia.com que é um construtor para inicializar todos os elementos da web é criado, o método selectCurrentDerivative () para selecionar o valor do campo suspenso Searchbox, selectSymbol () para selecionar um símbolo no página que aparece a seguir e verifytext () para verificar se o cabeçalho da página é o esperado ou não.
- NSE_MainClass.java é o arquivo de classe principal que chama todos os métodos acima e executa as respectivas ações no site NSE.
PagefactoryClass.java
package com.pagefactory.knowledge; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.PageFactory; import org.openqa.selenium.support.ui.Select; public class PagefactoryClass { WebDriver driver; @FindBy(id = 'QuoteSearch') WebElement Searchbox; @FindBy(id = 'cidkeyword') WebElement Symbol; @FindBy(id = 'companyName') WebElement pageText; public PagefactoryClass(WebDriver driver) { this.driver = driver; PageFactory.initElements(driver, this); } public void selectCurrentDerivative(String derivative) { Select select = new Select(Searchbox); select.selectByVisibleText(derivative); // 'Currency Derivatives' } public void selectSymbol(String symbol) { Symbol.sendKeys(symbol); } public void verifytext() { if (pageText.getText().equalsIgnoreCase('U S Dollar-Indian Rupee - USDINR')) { System.out.println('Page Header is as expected'); } else System.out.println('Page Header is NOT as expected'); } }
NSE_MainClass.java
package com.pagefactory.knowledge; import java.util.List; import java.util.concurrent.TimeUnit; import org.openqa.selenium.By; import org.openqa.selenium.StaleElementReferenceException; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; public class NSE_MainClass { static PagefactoryClass page; static WebDriver driver; public static void main(String() args) { System.setProperty('webdriver.chrome.driver', 'C:\Users\eclipse-workspace\automation-framework\src\test\java\Drivers\chromedriver.exe'); driver = new ChromeDriver(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.get('https://www.nseindia.com/'); driver.manage().window().maximize(); test_Home_Page_ofNSE(); } public static void test_Home_Page_ofNSE() throws StaleElementReferenceException { page = new PagefactoryClass(driver); page.selectCurrentDerivative('Currency Derivatives'); page.selectSymbol('USD'); List Options = driver.findElements(By.xpath('//span(contains(.,'USD'))')); int count = Options.size(); for (int i = 0; i Exemplo 2:
- Vá para ‘https://www.shoppersstop.com/brands’
- Navegue até o link Haute curry.
- Verifique se a página Haute Curry contém o texto “Começar Novo Algo”.
Estrutura do programa
- shopperstopPagefactory.java que inclui um repositório de objetos usando o conceito pagefactory para shoppersstop.com que é um construtor para inicializar todos os elementos da web é criado, métodos closeExtraPopup () para lidar com uma caixa pop-up de alerta que se abre, clickOnHauteCurryLink () para clicar em Haute Curry Vincule e verifiqueStartNewSomething () para verificar se a página Haute Curry contém o texto “Iniciar algo novo”.
- Shopperstop_CallPagefactory.java é o arquivo de classe principal que chama todos os métodos acima e executa as respectivas ações no site NSE.
shopperstopPagefactory.java
package com.inportia.automation_framework; import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.PageFactory; public class shopperstopPagefactory { WebDriver driver; @FindBy(id='firstVisit') WebElement extrapopup; @FindBy(xpath='//img(@src='https://sslimages.shoppersstop.com /sys-master/root/haf/h3a/9519787376670/brandMedia_HauteCurry_logo.png')') WebElement HCLink; @FindBy(xpath='/html/body/main/footer/div(1)/p') WebElement Startnew; public shopperstopPagefactory(WebDriver driver) { this.driver=driver; PageFactory.initElements(driver, this); } public void closeExtraPopup() { extrapopup.click(); } public void clickOnHauteCurryLink() { JavascriptExecutor js = (JavascriptExecutor) driver; js.executeScript('arguments(0).click();',HCLink); js.executeAsyncScript('window.setTimeout(arguments(arguments.length - 1), 10000);'); if(driver.getCurrentUrl().equals('https://www.shoppersstop.com/haute-curry')) { System.out.println('We are on the Haute Curry page'); } else { System.out.println('We are NOT on the Haute Curry page'); } } public void verifyStartNewSomething() { if (Startnew.getText().equalsIgnoreCase('Start Something New')) { System.out.println('Start new something text exists'); } else System.out.println('Start new something text DOESNOT exists'); } }
Shopperstop_CallPagefactory.java
package com.inportia.automation_framework; import java.util.concurrent.TimeUnit; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; public class Shopperstop_CallPagefactory extends shopperstopPagefactory { public Shopperstop_CallPagefactory(WebDriver driver) { super(driver); // TODO Auto-generated constructor stub } static WebDriver driver; public static void main(String() args) { System.setProperty('webdriver.chrome.driver', 'C:\eclipse-workspace\automation-framework\src\test\java\Drivers\chromedriver.exe'); driver = new ChromeDriver(); Shopperstop_CallPagefactory s1=new Shopperstop_CallPagefactory(driver); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.get('https://www.shoppersstop.com/brands'); s1.clickOnHauteCurryLink(); s1.verifyStartNewSomething(); } }
POM usando o Page Factory
Tutoriais em vídeo - POM com fábrica de páginas
Parte I
parte II
Uma classe Factory é usada para tornar o uso de objetos de página mais simples e fácil.
- Primeiro, precisamos encontrar os elementos da web por anotação @FindBy nas aulas de página .
- Em seguida, inicialize os elementos usando initElements () ao instanciar a classe de página.
# 1) @FindBy:
A anotação @FindBy é usada em PageFactory para localizar e declarar os elementos da web usando diferentes localizadores.Aqui, passamos o atributo, bem como seu valor usado para localizar o elemento da web para a anotação @FindBy e, em seguida, o WebElement é declarado.
Existem 2 maneiras de usar a anotação.
Por exemplo:
@FindBy(how = How.ID, using='EmailAddress') WebElement Email; @FindBy(id='EmailAddress') WebElement Email;
No entanto, o primeiro é a forma padrão de declarar WebElements.
'Quão' é uma classe e tem variáveis estáticas como ID, XPATH, CLASSNAME, LINKTEXT, etc.
'usando' - Para atribuir um valor a uma variável estática.
No acima exemplo , usamos o atributo ‘id’ para localizar o elemento da web ‘Email’. Da mesma forma, podemos usar os seguintes localizadores com as anotações @FindBy:
- nome da classe
- css
- nome
- xpath
- tagName
- Texto do link
- parcialLinkText
# 2) initElements ():
O initElements é um método estático da classe PageFactory que é usado para inicializar todos os elementos da web localizados pela anotação @FindBy. Assim, instanciando as classes da página facilmente.
initElements(WebDriver driver, java.lang.Class pageObjectClass)
Devemos também compreender que o POM segue os princípios OOPS.
- WebElements são declarados como variáveis de membro privado (Data Hiding).
- Vinculando WebElements com métodos correspondentes (encapsulamento).
Etapas para criar POM usando o padrão de fábrica de página
# 1) Crie um arquivo de classe Java separado para cada página da web.
#dois) Em cada classe, todos os WebElements devem ser declarados como variáveis (usando a anotação - @FindBy) e inicializados usando o método initElement (). Os WebElements declarados devem ser inicializados para serem usados nos métodos de ação.
# 3) Defina os métodos correspondentes que atuam nessas variáveis.
Vamos dar um exemplo de um cenário simples:
- Abra o URL de um aplicativo.
- Digite os dados do endereço de e-mail e da senha.
- Clique no botão Login.
- Verifique a mensagem de login bem-sucedido na página de pesquisa.
Camada de Página
Aqui temos 2 páginas,
- Pagina inicial - A página que se abre quando o URL é inserido e onde inserimos os dados para login.
- SearchPage - Uma página que é exibida após um login bem-sucedido.
Na Camada de Página, cada página no Aplicativo Web é declarada como uma Classe Java separada e seus localizadores e ações são mencionados lá.
Etapas para criar POM com exemplo em tempo real
# 1) Crie uma classe Java para cada página:
Nisso exemplo , acessaremos 2 páginas da web, páginas “Home” e “Search”.
Portanto, criaremos 2 classes Java na Camada de Página (ou em um pacote, digamos, com.automation.pages).
Package Name :com.automation.pages HomePage.java SearchPage.java
# 2) Defina WebElements como variáveis usando Annotation @FindBy:
Estaríamos interagindo com:
- E-mail, senha, campo do botão Login na página inicial.
- Mensagem de sucesso na página de pesquisa.
Portanto, definiremos WebElements usando @FindBy
Por exemplo: Se vamos identificar o EmailAddress usando o id do atributo, então sua declaração de variável é
//Locator for EmailId field @FindBy(how=How.ID,using='EmailId') private WebElementEmailIdAddress;
# 3) Crie métodos para ações executadas em WebElements.
Abaixo as ações são realizadas em WebElements:
- Digite a ação no campo Endereço de e-mail.
- Digite ação no campo Senha.
- Clique em ação no botão de login.
Por exemplo, Métodos definidos pelo usuário são criados para cada ação no WebElement como,
public void typeEmailId(String Id){ driver.findElement(EmailAddress).sendKeys(Id) }
Aqui, o Id é passado como parâmetro no método, pois a entrada será enviada pelo usuário a partir do caso de teste principal.
Observação :Um construtor deve ser criado em cada classe da Camada de Página, a fim de obter a instância do driver da classe Principal na Camada de Teste e também para inicializar WebElements (Objetos de Página) declarados na classe de página usando PageFactory.InitElement () .
Não iniciamos o driver aqui, em vez disso, sua instância é recebida da Classe Principal quando o objeto da classe Camada de Página é criado.
InitElement () - é usado para inicializar os WebElements declarados, usando a instância do driver da classe principal. Em outras palavras, WebElements são criados usando a instância do driver. Somente depois que os WebElements são inicializados, eles podem ser usados nos métodos para realizar ações.
Duas classes Java são criadas para cada página, conforme mostrado abaixo:
HomePage.java
//package com.automation.pages; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; public class HomePage { WebDriver driver; // Locator for Email Address @FindBy(how=How.ID,using='EmailId') private WebElement EmailIdAddress; // Locator for Password field @FindBy(how=How.ID,using='Password ') private WebElement Password; // Locator for SignIn Button @FindBy(how=How.ID,using='SignInButton') private WebElement SignInButton; // Method to type EmailId public void typeEmailId(String Id){ driver.findElement(EmailAddress).sendKeys(Id) } // Method to type Password public void typePassword(String PasswordValue){ driver.findElement(Password).sendKeys(PasswordValue) } // Method to click SignIn Button public void clickSignIn(){ driver.findElement(SignInButton).click() } // Constructor // Gets called when object of this page is created in MainClass.java public HomePage(WebDriver driver) { // 'this' keyword is used here to distinguish global and local variable 'driver' //gets driver as parameter from MainClass.java and assigns to the driver instance in this class this.driver=driver; PageFactory.initElements(driver,this); // Initialises WebElements declared in this class using driver instance. } }
SearchPage.Java
//package com.automation.pages; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; public class SearchPage{ WebDriver driver; // Locator for Success Message @FindBy(how=How.ID,using='Message') private WebElement SuccessMessage; // Method that return True or False depending on whether the message is displayed public Boolean MessageDisplayed(){ Boolean status = driver.findElement(SuccessMessage).isDisplayed(); return status; } // Constructor // This constructor is invoked when object of this page is created in MainClass.java public SearchPage(WebDriver driver) { // 'this' keyword is used here to distinguish global and local variable 'driver' //gets driver as parameter from MainClass.java and assigns to the driver instance in this class this.driver=driver; PageFactory.initElements(driver,this); // Initialises WebElements declared in this class using driver instance. } }
Camada de Teste
Casos de teste são implementados nesta classe. Criamos um pacote separado, digamos, com.automation.test e, em seguida, criamos uma classe Java aqui (MainClass.java)
Etapas para criar casos de teste:
- Inicialize o driver e abra o aplicativo.
- Crie um objeto da classe PageLayer (para cada página da web) e passe a instância do driver como parâmetro.
- A partir do objeto criado, faça uma chamada aos métodos da classe PageLayer (para cada página da web) para realizar ações / verificação.
- Repita a etapa 3 até que todas as ações sejam realizadas e feche o driver.
//package com.automation.test; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; public class MainClass { public static void main(String() args) { System.setProperty('webdriver.chrome.driver','./exefiles/chromedriver.exe'); WebDriver driver= new ChromeDriver(); driver.manage().window().maximize(); driver.get('URL mentioned here'); // Creating object of HomePage and driver instance is passed as parameter to constructor of Homepage.Java HomePage homePage= new HomePage(driver); // Type EmailAddress homePage.typeEmailId('abc@ymail.com'); // EmailId value is passed as paramter which in turn will be assigned to the method in HomePage.Java // Type Password Value homePage.typePassword('password123'); // Password value is passed as paramter which in turn will be assigned to the method in HomePage.Java // Click on SignIn Button homePage.clickSignIn(); // Creating an object of LoginPage and driver instance is passed as parameter to constructor of SearchPage.Java SearchPage searchPage= new SearchPage(driver); //Verify that Success Message is displayed Assert.assertTrue(searchPage.MessageDisplayed()); //Quit browser driver.quit(); } }
Hierarquia de tipo de anotação usada para declarar WebElements
As anotações são usadas para ajudar a construir uma estratégia de localização para os Elementos de UI.
# 1) @FindBy
Quando se trata de Pagefactory, @FindBy atua como uma varinha mágica. Ele adiciona todo o poder ao conceito. Você agora está ciente de que a anotação @FindBy em Pagefactory tem o mesmo desempenho do driver.findElement () no modelo de objeto de página normal. É usado para localizar WebElement / WebElements com um critério .
# 2) @FindBys
É usado para localizar WebElement com mais de um critério e precisa atender a todos os critérios fornecidos. Esses critérios devem ser mencionados em um relacionamento pai-filho. Em outras palavras, isso usa relacionamento condicional AND para localizar os WebElements usando os critérios especificados. Ele usa vários @FindBy para definir cada critério.
Por exemplo:
Código-fonte HTML de um WebElement:
No POM:
@FindBys({ @FindBy(id = 'searchId_1'), @FindBy(name = 'search_field') }) WebElementSearchButton;
No exemplo acima, o WebElement ‘SearchButton’ está localizado apenas se combina com ambos os critérios cujo valor de id é “searchId_1” e o valor do nome é “search_field”. Observe que o primeiro critério pertence a uma tag pai e o segundo critério a uma tag filho.
# 3) @FindAll
É usado para localizar WebElement com mais de um critério e precisa corresponder a pelo menos um dos critérios fornecidos. Isso usa relacionamentos condicionais OR para localizar WebElements. Ele usa vários @FindBy para definir todos os critérios.
Por exemplo:
HTML SourceCode:
No POM:
@FindBys({ @FindBy(id = 'UsernameNameField_1'), // doesn’t match @FindBy(name = 'User_Id') //matches @FindBy(className = “UserName_r”) //matches }) WebElementUserName;
No exemplo acima, o WebElement ‘Nome de usuário está localizado se corresponde a pelo menos um dos critérios mencionados.
# 4) @CacheLookUp
Quando o WebElement é usado com mais frequência em casos de teste, o Selenium procura o WebElement cada vez que o script de teste é executado. Nesses casos, em que certos WebElements são usados globalmente para todos os TC ( Por exemplo, O cenário de login acontece para cada TC), essa anotação pode ser usada para manter esses WebElements na memória cache, uma vez que é lido pela primeira vez.
Isso, por sua vez, ajuda o código a ser executado mais rapidamente porque, a cada vez, ele não precisa procurar o WebElement na página, mas pode obter sua referência da memória.
Pode ser um prefixo com qualquer um de @FindBy, @FindBys e @FindAll.
Por exemplo:
@CacheLookUp @FindBys({ @FindBy(id = 'UsernameNameField_1'), @FindBy(name = 'User_Id') @FindBy(className = “UserName_r”) }) WebElementUserName;
Observe também que esta anotação deve ser usada apenas para WebElements cujo valor de atributo (como xpath, nome de id, nome de classe, etc.) não muda com frequência. Assim que o WebElement é localizado pela primeira vez, ele mantém sua referência na memória cache.
Então, se ocorrer uma mudança no atributo do WebElement após alguns dias, o Selenium não conseguirá localizar o elemento, pois já tem sua referência antiga em sua memória cache e não considerará a mudança recente no WebElement.
Mais em PageFactory.initElements ()
Agora que entendemos a estratégia do Pagefactory ao inicializar os elementos da web usando InitElements (), vamos tentar entender as diferentes versões do método.
O método, como sabemos, leva o objeto driver e o objeto de classe atual como parâmetros de entrada e retorna o objeto de página inicializando implícita e proativamente todos os elementos da página.
Na prática, o uso do construtor conforme mostrado na seção acima é mais preferível do que as outras formas de seu uso.
Formas alternativas de chamar o método:
# 1) Em vez de usar o ponteiro “this”, você pode criar o objeto da classe atual, passar a instância do driver para ele e chamar o método estático initElements com parâmetros, ou seja, o objeto do driver e o objeto da classe que acabou de ser criado.
public PagefactoryClass(WebDriver driver) { //version 2 PagefactoryClass page=new PagefactoryClass(driver); PageFactory.initElements(driver, page); }
#dois) A terceira maneira de inicializar elementos usando a classe Pagefactory é usando a API chamada “reflexão”. Sim, em vez de criar um objeto de classe com uma palavra-chave “nova”, classname.class pode ser passado como parte do parâmetro de entrada initElements ().
public PagefactoryClass(WebDriver driver) { //version 3 PagefactoryClass page=PageFactory.initElements(driver, PagefactoryClass.class); }
perguntas frequentes
P # 1) Quais são as diferentes estratégias de localização usadas para @FindBy?
Responda: A resposta simples para isso é que não há estratégias diferentes de localizador usadas para @FindBy.
Eles usam as mesmas 8 estratégias de localização que o método findElement () no POM normal usa:
- eu ia
- nome
- nome da classe
- xpath
- css
- tagName
- Texto do link
- parcialLinkText
P # 2) Existem versões diferentes para o uso de anotações @FindBy também?
Responda: Quando existe um elemento da web a ser pesquisado, usamos a anotação @FindBy. Iremos elaborar sobre as formas alternativas de usar o @FindBy junto com as diferentes estratégias de localização também.
Já vimos como usar a versão 1 de @FindBy:
@FindBy(id = 'cidkeyword') WebElement Symbol;
A versão 2 de @FindBy é passando o parâmetro de entrada como Quão e Usando .
Quão procura a estratégia de localização por meio da qual o elemento da web seria identificado. A palavra-chave usando define o valor do localizador.
Veja abaixo para melhor compreensão,
- How.ID pesquisa o elemento usando eu ia estratégia e o elemento que tenta identificar tem id = cidkeyword.
@FindBy(how = How.ID, using = ' cidkeyword') WebElement Symbol;
- Como.CLASS_NAME pesquisa o elemento usando nome da classe estratégia e o elemento que ela tenta identificar tem classe = newclass.
@FindBy(how = How.CLASS_NAME, using = 'newclass') WebElement Symbol;
P # 3) Existe uma diferença entre as duas versões de @FindBy?
Responda: A resposta é não, não há diferença entre as duas versões. Acontece que a primeira versão é a mais curta e fácil quando comparada à segunda versão.
P # 4) O que devo usar na pagefactory caso haja uma lista de elementos da web a serem localizados?
Responda: No padrão de design de objeto de página usual, temos driver.findElements () para localizar vários elementos pertencentes à mesma classe ou nome de tag, mas como localizamos esses elementos no caso do modelo de objeto de página com Pagefactory? A maneira mais fácil de obter tais elementos é usar a mesma anotação @FindBy.
Eu entendo que esta linha parece ser um arranha-céus para muitos de vocês. Mas sim, é a resposta à pergunta.
Vejamos o exemplo abaixo:
Usando o modelo de objeto de página normal sem Pagefactory, você usa driver.findElements para localizar vários elementos, conforme mostrado abaixo:
private List multipleelements_driver_findelements = driver.findElements (By.class(“last”));
O mesmo pode ser alcançado usando o modelo de objeto de página com Pagefactory conforme fornecido abaixo:
@FindBy (how = How.CLASS_NAME, using = 'last') private List multipleelements_FindBy;
Basicamente, atribuir os elementos a uma lista do tipo WebElement funciona independentemente de a Pagefactory ter sido usada ou não durante a identificação e localização dos elementos.
P # 5) O design do objeto Página sem pagefactory e com Pagefactory pode ser usado no mesmo programa?
Responda: Sim, tanto o design de objeto de página sem Pagefactory quanto com Pagefactory podem ser usados no mesmo programa. Você pode seguir o programa fornecido abaixo no Resposta para a pergunta # 6 para ver como ambos são usados no programa.
Uma coisa a lembrar é que o conceito de Pagefactory com o recurso de cache deve ser evitado em elementos dinâmicos, enquanto o design de objeto de página funciona bem para elementos dinâmicos. No entanto, o Pagefactory serve apenas para elementos estáticos.
P # 6) Existem maneiras alternativas de identificar elementos com base em vários critérios?
como adicionar um inteiro a um array em java
Responda: A alternativa para identificar elementos com base em vários critérios é usar as anotações @FindAll e @FindBys. Essas anotações ajudam a identificar um ou vários elementos, dependendo dos valores obtidos dos critérios passados.
# 1) @FindAll:
@FindAll pode conter vários @FindBy e retornará todos os elementos que correspondem a qualquer @FindBy em uma única lista. @FindAll é usado para marcar um campo em um objeto de página para indicar que a pesquisa deve usar uma série de tags @FindBy. Em seguida, ele pesquisará todos os elementos que correspondam a qualquer um dos critérios FindBy.
Observe que não é garantido que os elementos estejam na ordem do documento.
A sintaxe para usar @FindAll é a seguinte:
@FindAll( { @FindBy(how = How.ID, using = 'foo'), @FindBy(className = 'bar') } )
Explicação: @FindAll irá pesquisar e identificar elementos separados em conformidade com cada um dos critérios @FindBy e listá-los. No exemplo acima, ele irá primeiro pesquisar um elemento cujo id = ”foo” e então, irá identificar o segundo elemento com className = ”bar”.
Supondo que haja um elemento identificado para cada critério FindBy, @FindAll resultará na listagem de 2 elementos, respectivamente. Lembre-se de que pode haver vários elementos identificados para cada critério. Assim, em palavras simples, @ Encontrar tudo atos equivalentes ao OU operador nos critérios @FindBy aprovados.
# 2) @FindBys:
FindBys é usado para marcar um campo em um objeto de página para indicar que a pesquisa deve usar uma série de tags @FindBy em uma cadeia, conforme descrito em ByChained. Quando os objetos WebElement necessários precisam corresponder a todos os critérios fornecidos, use a anotação @FindBys.
A sintaxe para usar @FindBys é a seguinte:
@FindBys( { @FindBy(name=”foo”) @FindBy(className = 'bar') } )
Explicação: @FindBys irá pesquisar e identificar elementos em conformidade com todos os critérios @FindBy e listá-los. No exemplo acima, ele pesquisará os elementos cujo nome = ”foo” e className = ”bar”.
@FindAll resultará na listagem de 1 elemento se presumirmos que havia um elemento identificado com o nome e o className nos critérios fornecidos.
Se não houver um elemento que satisfaça todas as condições FindBy passadas, a resultante de @FindBys será zero elementos. Pode haver uma lista de elementos da web identificados se todas as condições atenderem a vários elementos. Em palavras simples, @ FindBys atos equivalentes ao E operador nos critérios @FindBy aprovados.
Vamos ver a implementação de todas as anotações acima por meio de um programa detalhado:
Modificaremos o programa www.nseindia.com dado na seção anterior para entender a implementação das anotações @FindBy, @FindBys e @FindAll
# 1) O repositório de objetos de PagefactoryClass é atualizado conforme abaixo:
List newlist = driver.findElements (By.tagName (“a”));
@FindBy (como = como. TAG_NAME , usando = “a”)
privado Lista findbyvalue;
@Encontrar tudo ({ @FindBy (className = “sel”), @FindBy (xpath = ”// a (@ id =’ tab5 ′) ”)})
privado Lista findallvalue;
@FindBys ({ @FindBy (className = “sel”), @FindBy (xpath = ”// a (@ id =’ tab5 ′) ”)})
privado Lista findbysvalue;
# 2) Um novo método seeHowFindWorks () é escrito na PagefactoryClass e é chamado como o último método na classe Main.
O método é o seguinte:
private void seeHowFindWorks() { System.out.println('driver.findElements(By.tagName()) '+newlist.size()); System.out.println('count of @FindBy- list elements '+findbyvalue.size()); System.out.println('count of @FindAll elements '+findallvalue.size()); for(int i=0;i A seguir está o resultado mostrado na janela do console após a execução do programa:

Vamos agora tentar entender o código em detalhes:
# 1) Por meio do padrão de design do objeto de página, o elemento ‘newlist’ identifica todas as tags com a âncora ‘a’. Em outras palavras, obtemos uma contagem de todos os links da página.
Aprendemos que a pagefactory @FindBy faz o mesmo trabalho que a driver.findElement (). O elemento findbyvalue é criado para obter a contagem de todos os links na página por meio de uma estratégia de busca com um conceito pagefactory.
Está correto que tanto driver.findElement () quanto @FindBy fazem o mesmo trabalho e identificam os mesmos elementos. Se você olhar a captura de tela da janela de console resultante acima, a contagem de links identificados com o elemento newlist e a de findbyvalue são iguais, ou seja, 299 links encontrados na página.
O resultado mostrado abaixo:
driver.findElements(By.tagName()) 299 count of @FindBy- list elements 299
#dois) Aqui elaboramos o funcionamento da anotação @FindAll que será referente à lista dos elementos da web com o nome findallvalue.
Olhando atentamente para cada critério @FindBy dentro da anotação @FindAll, o primeiro critério @FindBy procura elementos com className = 'sel' e o segundo critério @FindBy procura um elemento específico com XPath = “// a (@ id = 'tab5')
Vamos agora pressionar F12 para inspecionar os elementos na página nseindia.com e obter alguns esclarecimentos sobre os elementos correspondentes aos critérios @FindBy.
Existem dois elementos na página que correspondem a className = ”sel”:
para) O elemento “Fundamentos” tem a tag de lista, ou seja,
com className = ”sel”. Veja o instantâneo abaixo

b) Outro elemento 'Livro de pedidos' tem um XPath com uma tag âncora que tem o nome da classe como ‘sel’.

c) O segundo @FindBy com XPath tem uma tag âncora cujo eu ia é ' tab5 ”. Há apenas um elemento identificado em resposta à pesquisa que é Fundamentos.
Veja o instantâneo abaixo:

Quando o teste nseindia.com foi executado, obtivemos a contagem dos elementos pesquisados por.
@FindAll as 3. Os elementos para findallvalue quando exibidos foram: Fundamentals as the 0ºelemento de índice, livro de pedidos como o 1stelemento de índice e fundamentos novamente como o 2WLelemento de índice. Já aprendemos que @FindAll identifica elementos para cada critério @FindBy separadamente.
Pelo mesmo protocolo, para a pesquisa de primeiro critério, ou seja, className = 'sel', ele identificou dois elementos que satisfazem a condição e buscou 'Fundamentos' e 'Livro de pedidos'.
Em seguida, ele mudou para o próximo critério @FindBy e de acordo com o xpath fornecido para o segundo @FindBy, ele poderia buscar o elemento ‘Fundamentos’. É por isso que ele finalmente identificou 3 elementos, respectivamente.
Assim, ele não obtém os elementos que satisfazem nenhuma das condições @FindBy, mas lida separadamente com cada um dos @FindBy e identifica os elementos da mesma forma. Além disso, no exemplo atual, também vimos que ele não observa se os elementos são únicos ( Por exemplo. O elemento 'Fundamentos', neste caso, exibido duas vezes como parte do resultado dos dois critérios @FindBy)
# 3) Aqui elaboramos o funcionamento da anotação @FindBys que será referente à lista dos elementos da web com o nome findbysvalue. Aqui também, o primeiro critério @FindBy busca elementos com className = ’sel’ e o segundo critério @FindBy procura um elemento específico com xpath = “// a (@ id =” tab5 ”).
Agora que sabemos, os elementos identificados para a primeira condição @FindBy são “Fundamentos” e “Livro de pedidos” e o do segundo critério @FindBy é “Fundamentos”.
Então, como o resultado @FindBys será diferente do @FindAll? Aprendemos na seção anterior que @FindBys é equivalente ao operador condicional AND e, portanto, procura um elemento ou a lista de elementos que satisfaça todas as condições @FindBy.
De acordo com nosso exemplo atual, o valor “Fundamentos” é o único elemento que possui class = ”sel” e id = ”tab5”, portanto, satisfazendo ambas as condições. É por isso que o tamanho de @FindBys em nosso caso de teste é 1 e exibe o valor como “Fundamentos”.
Armazenando Elementos em Cache no Pagefactory
Cada vez que uma página é carregada, todos os elementos da página são pesquisados novamente, invocando uma chamada por meio de @FindBy ou driver.findElement () e há uma nova pesquisa dos elementos na página.
Na maioria das vezes, quando os elementos são dinâmicos ou mudam continuamente durante o tempo de execução, especialmente se forem elementos AJAX, certamente faz sentido que, a cada carregamento de página, haja uma nova busca por todos os elementos da página.
Quando a página da web tem elementos estáticos, o armazenamento em cache do elemento pode ajudar de várias maneiras. Quando os elementos são armazenados em cache, ele não precisa localizar os elementos novamente ao carregar a página, em vez disso, pode fazer referência ao repositório de elementos em cache. Isso economiza muito tempo e melhora o desempenho.
O Pagefactory fornece esse recurso de armazenamento em cache dos elementos usando uma anotação @CacheLookUp .
A anotação diz ao driver para usar a mesma instância do localizador do DOM para os elementos e não pesquisá-los novamente, enquanto o método initElements do pagefactory contribui de forma proeminente para armazenar o elemento estático em cache. Os initElements fazem o trabalho de cache dos elementos.
Isso torna o conceito de pagefactory especial em relação ao padrão de design de objeto de página regular. Ele vem com seus prós e contras, que discutiremos um pouco mais tarde. Por exemplo, o botão de login na página inicial do Facebook é um elemento estático, que pode ser armazenado em cache e é um elemento ideal para ser armazenado em cache.
Vejamos agora como implementar a anotação @CacheLookUp
Você precisará primeiro importar um pacote para o Cachelookup conforme abaixo:
import org.openqa.selenium.support.CacheLookup
Abaixo está o snippet exibindo a definição de um elemento usando @CacheLookUp. Assim que o UniqueElement é procurado pela primeira vez, o initElement () armazena a versão em cache do elemento para que da próxima vez o driver não procure o elemento, em vez disso, ele se refere ao mesmo cache e executa a ação no elemento certo um jeito.
@FindBy(id = 'unique') @CacheLookup private WebElement UniqueElement;
Vamos agora ver através de um programa real como as ações no elemento da web em cache são mais rápidas do que no elemento da web não armazenado em cache:
Aprimorando ainda mais o programa nseindia.com, escrevi outro novo método monitorPerformance () no qual crio um elemento armazenado em cache para a caixa de pesquisa e um elemento não armazenado em cache para a mesma caixa de pesquisa.
Em seguida, tento obter o tagname do elemento 3000 vezes para ambos os elementos em cache e não em cache e tento avaliar o tempo gasto para concluir a tarefa pelos elementos em cache e não armazenados em cache.
Considerei 3.000 vezes para que possamos ver uma diferença visível nos tempos dos dois. Devo esperar que o elemento em cache conclua a obtenção do tagname 3000 vezes em menos tempo quando comparado ao elemento não armazenado em cache.
Agora sabemos porque o elemento em cache deve funcionar mais rápido, ou seja, o driver é instruído a não procurar o elemento após a primeira pesquisa, mas continuar trabalhando diretamente nele e esse não é o caso com o elemento não armazenado em cache onde a pesquisa de elemento é feita para todas as 3000 vezes e então a ação é executada nele.
Abaixo está o código para o método monitorPerformance ():
private void monitorPerformance() { //non cached element long NoCache_StartTime = System.currentTimeMillis(); for(int i = 0; i <3000; i ++) { Searchbox.getTagName(); } long NoCache_EndTime = System.currentTimeMillis(); long NoCache_TotalTime=(NoCache_EndTime-NoCache_StartTime)/1000; System.out.println('Response time without caching Searchbox ' + NoCache_TotalTime+ ' seconds'); //cached element long Cached_StartTime = System.currentTimeMillis(); for(int i = 0; i < 3000; i ++) { cachedSearchbox.getTagName(); } long Cached_EndTime = System.currentTimeMillis(); long Cached_TotalTime=(Cached_EndTime - Cached_StartTime)/1000; System.out.println('Response time by caching Searchbox ' + Cached_TotalTime+ ' seconds'); }
Na execução, veremos o resultado abaixo na janela do console:
De acordo com o resultado, a tarefa no elemento não armazenado em cache é concluída em 82 segundos, enquanto o tempo necessário para concluir a tarefa no elemento em cache foi apenas 37 segundos. Esta é de fato uma diferença visível no tempo de resposta do elemento armazenado em cache e não armazenado em cache.

P # 7) Quais são os prós e contras da anotação @CacheLookUp no conceito de Pagefactory?
Responda:
Prós @CacheLookUp e situações viáveis para seu uso:
@CacheLookUp é viável quando os elementos são estáticos ou não mudam enquanto a página é carregada. Esses elementos não alteram o tempo de execução. Nesses casos, é aconselhável usar a anotação para melhorar a velocidade geral da execução do teste.
Contras da anotação @CacheLookUp:
A maior desvantagem de ter elementos armazenados em cache com a anotação é o medo de obter StaleElementReferenceExceptions com frequência.
Os elementos dinâmicos são atualizados com bastante frequência com aqueles que são suscetíveis a alterações rapidamente em alguns segundos ou minutos do intervalo de tempo.
Abaixo estão algumas dessas instâncias dos elementos dinâmicos:
- Ter um cronômetro na página da web que mantém o cronômetro atualizado a cada segundo.
- Um quadro que atualiza constantemente o boletim meteorológico.
- Uma página relatando as atualizações ao vivo do Sensex.
Eles não são ideais ou viáveis para o uso da anotação @CacheLookUp. Se o fizer, corre o risco de obter a exceção de StaleElementReferenceExceptions.
Ao armazenar em cache tais elementos, durante a execução do teste, o DOM dos elementos é alterado, no entanto, o driver procura a versão do DOM que já foi armazenada durante o armazenamento em cache. Isso faz com que o elemento obsoleto seja pesquisado pelo driver que não existe mais na página da web. É por isso que StaleElementReferenceException é lançada.
Aulas de fábrica:
Pagefactory é um conceito construído em várias classes e interfaces de fábrica. Aprenderemos sobre algumas classes e interfaces de fábrica aqui nesta seção. Poucos dos quais veremos são AjaxElementLocatorFactory , ElementLocatorFactory e DefaultElementFactory.
Alguma vez nós já nos perguntamos se o Pagefactory fornece alguma maneira de incorporar a espera Implícita ou Explícita pelo elemento até que uma determinada condição seja satisfeita ( Exemplo: Até que um elemento seja visível, habilitado, clicável, etc.)? Se sim, aqui está uma resposta apropriada para isso.
AjaxElementLocatorFactory é um dos contribuintes significativos entre todas as classes de fábrica. A vantagem de AjaxElementLocatorFactory é que você pode atribuir um valor de tempo limite para um elemento da web à classe da página Object.
Embora o Pagefactory não forneça um recurso de espera explícito, há uma variante da espera implícita usando a classe AjaxElementLocatorFactory . Essa classe pode ser usada incorporada quando o aplicativo usa componentes e elementos Ajax.
Aqui está como você o implementa no código. Dentro do construtor, quando usamos o método initElements (), podemos usar AjaxElementLocatorFactory para fornecer uma espera implícita nos elementos.
PageFactory.initElements(driver, this); can be replaced with PageFactory.initElements( new AjaxElementLocatorFactory(driver, 20), this);
A segunda linha do código acima implica que o driver deve definir um tempo limite de 20 segundos para todos os elementos na página quando cada um de seus carregamentos e se algum dos elementos não for encontrado após uma espera de 20 segundos, 'NoSuchElementException' é lançado para esse elemento ausente.
Você também pode definir a espera como abaixo:
public pageFactoryClass(WebDriver driver) { ElementLocatorFactory locateMe = new AjaxElementLocatorFactory(driver, 30); PageFactory.initElements(locateMe, this); this.driver = driver; }
O código acima funciona perfeitamente porque a classe AjaxElementLocatorFactory implementa a interface ElementLocatorFactory.
Aqui, a interface pai (ElementLocatorFactory) se refere ao objeto da classe filha (AjaxElementLocatorFactory). Portanto, o conceito Java de “upcasting” ou “polimorfismo de tempo de execução” é usado ao atribuir um tempo limite usando AjaxElementLocatorFactory.
Com relação a como funciona tecnicamente, o AjaxElementLocatorFactory primeiro cria um AjaxElementLocator usando um SlowLoadableComponent que pode não ter terminado de carregar quando load () retornar. Após uma chamada para load (), o método isLoaded () deve continuar a falhar até que o componente seja totalmente carregado.
Em outras palavras, todos os elementos serão pesquisados recentemente sempre que um elemento for acessado no código, invocando uma chamada para locator.findElement () da classe AjaxElementLocator que então aplica um tempo limite até o carregamento por meio da classe SlowLoadableComponent.
Além disso, depois de atribuir o tempo limite via AjaxElementLocatorFactory, os elementos com a anotação @CacheLookUp não serão mais armazenados em cache, pois a anotação será ignorada.
Também há uma variação de como você pode Ligar para initElements () método e como você não deveria Ligar para AjaxElementLocatorFactory para atribuir tempo limite para um elemento.
# 1) Você também pode especificar um nome de elemento em vez do objeto de driver conforme mostrado abaixo no método initElements ():
PageFactory.initElements( , this);
O método initElements () na variante acima invoca internamente uma chamada para a classe DefaultElementFactory e o construtor de DefaultElementFactory aceita o objeto de interface SearchContext como um parâmetro de entrada. O objeto do driver da Web e um elemento da Web pertencem à interface SearchContext.
Nesse caso, o método initElements () será inicializado antecipadamente apenas para o elemento mencionado e nem todos os elementos na página da Web serão inicializados.
#dois) No entanto, aqui está uma reviravolta interessante neste fato que afirma como você não deve chamar o objeto AjaxElementLocatorFactory de uma maneira específica. Se eu usar a variante acima de initElements () junto com AjaxElementLocatorFactory, ele falhará.
Exemplo: O código a seguir, ou seja, passar o nome do elemento em vez do objeto do driver para a definição AjaxElementLocatorFactory não funcionará como o construtor da classe AjaxElementLocatorFactory leva apenas o objeto do driver da Web como parâmetro de entrada e, portanto, o objeto SearchContext com o elemento da web não funcionaria para ele.
PageFactory.initElements(new AjaxElementLocatorFactory(, 10), this);
P # 8) O uso do pagefactory é uma opção viável em relação ao padrão de design de objeto de página regular?
Responda: Esta é a pergunta mais importante que as pessoas têm e é por isso que pensei em abordá-la no final do tutorial. Agora sabemos o que entra e sai da Pagefactory a partir de seus conceitos, anotações usadas, recursos adicionais que oferece suporte, implementação por meio de código, os prós e os contras.
Ainda assim, permanecemos com esta questão essencial de que se o pagefactory tem tantas coisas boas, por que não devemos nos ater ao seu uso.
Pagefactory vem com o conceito de CacheLookUp, que vimos não ser viável para elementos dinâmicos como valores do elemento sendo atualizados com frequência. Então, pagefactory sem CacheLookUp, é uma boa opção? Sim, se os xpaths forem estáticos.
No entanto, a queda é que o aplicativo da era moderna é preenchido com elementos dinâmicos pesados onde sabemos que o design do objeto de página sem pagefactory funciona bem, mas o conceito de pagefactory funciona igualmente bem com xpaths dinâmicos? Talvez não. Aqui está um exemplo rápido:
Na página nseindia.com, vemos uma tabela conforme a seguir.

O xpath da mesa é
'//*(@id='tab9Content')/table/tbody/tr(+count+)/td(1)'
Queremos recuperar os valores de cada linha para a primeira coluna 'Comprar Qtde'. Para fazer isso, precisaremos incrementar o contador de linha, mas o índice da coluna permanecerá 1. Não há como passar esse XPath dinâmico na anotação @FindBy, pois a anotação aceita valores que são estáticos e nenhuma variável pode ser passada isto.
É aqui que o pagefactory falha completamente, enquanto o POM normal funciona muito bem com ele. Você pode facilmente usar um loop for para incrementar o índice de linha usando esses xpaths dinâmicos no método driver.findElement ().
Conclusão
O Modelo de Objeto de Página é um conceito de design ou padrão usado na estrutura de automação Selenium.
A convecção de nomenclatura de métodos é amigável no modelo de objeto de página. O código no POM é fácil de entender, reutilizável e passível de manutenção. No POM, se houver alguma alteração no elemento web então, basta fazer as alterações em sua respectiva classe, ao invés de editar todas as classes.
O Pagefactory, assim como o POM usual, é um conceito maravilhoso de se aplicar. No entanto, precisamos saber onde o POM usual é viável e onde o Pagefactory é adequado. Nos aplicativos estáticos (onde XPath e elementos são estáticos), o Pagefactory pode ser amplamente implementado com benefícios adicionais de melhor desempenho também.
Alternativamente, quando o aplicativo envolve elementos dinâmicos e estáticos, você pode ter uma implementação mista do pom com Pagefactory e sem Pagefactory de acordo com a viabilidade de cada elemento da web.
Autor: Este tutorial foi escrito por Shobha D. Ela trabalha como líder de projeto e vem com mais de 9 anos de experiência em manual, automação (Selenium, IBM Rational Functional Tester, Java) e teste de API (SOAPUI e Tenha certeza em Java) .
Agora é com você, para implementação adicional do Pagefactory.
Boa exploração !!!
=> Visite aqui para aprender o selênio do zero.
Leitura recomendada
- 30+ Melhores Tutoriais de Selênio: Aprenda Selênio com Exemplos Reais
- Scripts Eficientes do Selenium e Cenários de Solução de Problemas - Tutorial # 27 do Selenium
- Depurando Scripts Selenium com Logs (Tutorial Log4j) - Tutorial Selenium # 26
- Introdução ao JUnit Framework e seu uso no Selenium Script - Selenium Tutorial # 11
- 7 fatores que afetam a estimativa de teste do projeto de automação do Selenium - Tutorial do Selenium # 32
- Asserções no Selenium usando os frameworks Junit e TestNG
- Como usar o framework TestNG para criar scripts do Selenium - Tutorial # 12 do TestNG Selenium
- Aprenda a usar anotações TestNG no Selenium (com exemplos)