twitterfacebookgoogle pluslinkedinrss feedemail

sexta-feira, 16 de fevereiro de 2018

Selenium WebDriver: Tempo de Espera Explícito e Implícito




Podemos utilizar um tempo de espera para mitigar erros ao tentar acessar elementos utilizando o Selenium WebDriver.
Como exemplo usamos a linguagem Java e levarei em consideração que já utiliza o WebDriver, apresentando este recurso avançado.

Imaginamos que você tenha um teste automatizado que acessa os elementos da página de login e no botão de "OK" é enviado a ação de clicar.
Depois é redirecionado para outra página do sistema, onde tenho que clicar em outro botão confirmando o meu login.
Por infelicidade do destino, apresenta um erro ao tentar acessar o elemento do botão da segunda página.
Para ilustrar, repare no código abaixo:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class LoginPage {

 WebDriver driver;
 
 //Mapeamento dos Elementos da Página de Login
 @FindBy(id="Login")
 WebElement usuario;
 
 @FindBy(how=How.NAME,using="Senha")
 WebElement password;
 
 @FindBy(how=How.ID, using="BtnOK")
 WebElement botaoOK;
 
 @FindBy(how=How.ID, using="BtnConfirmaOK")
 WebElement confirmacaoBotaoSucess;
 
 
 public LoginPage(WebDriver driver) {
  super();
  this.driver = driver;
 }

 public void fazerLogin(String uid, String pass){
  
  // Define os valores de Login e Senha.
  usuario.sendKeys(uid);
  password.sendKeys(pass);
  
  // Envia ação de clicar no botão OK e redireciona para outra página.
  botaoOK.click();

  // Erro ocorre ao tentar acessar o elemento do botão que está em outra página.  
  confirmacaoBotaoSucess.click();
 } 
}

O erro é o bendito abaixo:

org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element

O erro é claro que não conseguiu localizar o elemento.
Acontece que quando redireciona de uma página para a outra, não temos um tempo de espera entre os passos (steps).
Este tempo seria o de renderizar a página, podendo neste tempo ocorrer lentidão na rede, servidores, etc.

Uma grande parcela de automatizadores utilizam o método Thread.sleep(), esta abordagem é errada, não sendo eficiente.
O sleep espera o tempo definido, assim podendo aumentar muito o tempo do seu teste e não evitando se tivermos uma demora maior na renderização da página.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
 public void fazerLogin(String uid, String pass){
  
  // Define os valores de Login e Senha.
  usuario.sendKeys(uid);
  password.sendKeys(pass);
  
  // Envia ação de clicar no botão OK e redireciona para outra página.
  botaoOK.click();
  
  //Abordagem errada é definir um tempo de espera fixo, utilizando o método abaixo.
  Thread.sleep(3000);
   
  // Erro ocorre ao tentar acessar o elemento do botão que está em outra página.  
  confirmacaoBotaoSucess.click();
 } 
}

A documentação do WebDriver recomenda duas formas de definir um tempo de espera.
O "Explicit and Implicit Waits" tem duas abordagens distintas.
Primeiramente, vamos definir o que é Implícito e Explícito.
Nosso velho amigo dicionário diz:

Implícito
O adjetivo implícito indica algo que não está claramente expresso, que está subentendido.
É sinônimo de subentendido, subjacente, latente, tácito e velado.

Explícito
O adjetivo explícito indica algo que está expresso de forma clara e precisa, sem ambiguidades ou restrições. É sinônimo de claro, manifesto, patente, preciso, categórico, terminante, declarado e compreensível.

O implícito é o mais usual e simples.
Defininos um tempo de timeout para todo o escopo de nossos testes.
Conforme o código abaixo, definimos o tempo de 60 segundos de timeout.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
 public void fazerLogin(String uid, String pass){
  
  //define um TimeOut para em caso de não encontrar elementos na página.
  driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);  

 
  // Define os valores de Login e Senha.
  usuario.sendKeys(uid);
  password.sendKeys(pass);
  
  // Envia ação de clicar no botão OK e redireciona para outra página.
  botaoOK.click();
   
  // Não irá occorer erro ao tentar acessar o elemento do botão que está em outra página.  
  confirmacaoBotaoSucess.click();
 } 

Definindo o driver.manage().timeouts().implicitlyWait(), o WebDriver irá demorar o tempo definido para gerar a exceção de erro.
Ele verifica a cada 500 milissegundo se o elemento referenciado foi criado.
Assim evitando o erro de NoSuchElementException e sendo uma forma eficiente, evitando de utilizar o Thread.sleep().
O valor do método implicitlyWait() pode ser definido logo após a criação do objeto driver, não sendo necessário definir esse valor toda hora.

A forma explícita é definida pelo tempo de espera para cada elemento.
No código abaixo, identificamos a criação do objeto WebDriverWait.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
 public void fazerLogin(String uid, String pass){
  
  // Define os valores de Login e Senha.
  usuario.sendKeys(uid);
  password.sendKeys(pass);
  
  // Envia ação de clicar no botão OK e redireciona para outra página.
  botaoOK.click();
   
  //Segunda Tela onde é redirecionado depois do login.
  //===> Usando recurso de Wait, para evitar exception de encontrar elemento na tela.
  WebDriverWait wait = new WebDriverWait(driver, 10);
  WebElement btnConfirmarOK = wait.until(ExpectedConditions.visibilityOf(confirmacaoBotaoSucess));
  btnConfirmarOK.click();
 }

Utilizando o objeto WebDriverWait definimos o tempo de timeout e através do método until dizemos a condição que esperamos.
Em casos que a aplicação fica processando um lote por tempo indefinido, onde irá cair por timeout implícito, a utilização do tempo de espera explícito é necessário.

ATENÇÃO:
Não misture os tempos de espera implícito e explícito.
O tempo de espera fica imprevisível, assim não sendo possível dizer quanto tempo irá demorar.
Quando for necessário utilizar o tempo de espera explícito, defina como:
driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);

3 comentários:

  1. Excelente explicação, clara e objetiva, obrigado.

    ResponderExcluir
  2. ainda estou aprendendo a automatizar, embora não tenha entendido 100% agregou bastante sim, obrigado.

    ResponderExcluir

 

Sobre o Blog

Neste blog irei compartilhar as minhas experiências e observações. Os temas serão variados, mas com ênfase em tecnologia. Inscreva-se nos nossos canais para receber atualizações.