Post

1 Star2 Stars3 Stars4 Stars5 Stars
Loading ... Loading ...

Ter um mecanismo de espera confiável é um dos maiores desafios quando estamos trabalhando com automação de testes pela UI. Neste post, vou explicar sobre os tipos de esperas no Selenium WebDriver (em Java) e como usá-las. No final do post, serão descritos dois casos um pouco mais complexos e como foram solucionados.
No Selenium WebDriver, de acordo com a própria documentação, existem dois tipos de esperas: implícita e explícita.
Implícita
A espera implícita serve, basicamente, para dizer ao WebDriver um tempo máximo pelo qual ele deve aguardar quando estiver tentando encontrar um elemento. Exemplo:

driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

Lembretes:

Tempo default é 0 (zero) segundos.
Basta setar o valor uma vez!
10 segundos costuma ser um tempo razoável.
É um recurso útil, mas não use somente ele. A espera explícita é mais flexível e confiável para seus testes, principalmente se a aplicação a ser testada usa muito JavaScript ou AJAX.

Explícita
A espera explícita diz ao WebDriver uma condição (ou tempo) para que ele aguarde antes de prosseguir com o teste. Um exemplo de espera explícita é o polêmico Thread.sleep(), que deve ser evitado ao máximo por ser uma má prática e por ser muito dependente do browser, da máquina onde os testes estão sendo rodados, ou até de alguma integração que sua aplicação possa ter com outros sistemas.
Com isso, use o WebDriverWait! Exemplo:

WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id(“botaoOk”)));

Lembrete:

Tempo de polling default é de 0,5 segundos (ou 500 milissegundos).

A classe ExpectedConditions
Na classe ExpectedConditions, existem várias condições predefinidas para usar nos seus testes. Abaixo, vou listar as condições que mais uso e dar algumas dicas.
Visibilidade de elementos

visibilityOfElement / visibilityOfElementLocated

Dica: opte por essa ExpectedCondition em vez da “presenceOfElement“. A “presence” verifica apenas que o elemento está no DOM, enquanto a “visibility” verifica que o elemento está presente E enabled (ou seja, disponível para interação).
Texto presente em elemento

textToBePresentInElement / textToBePresentInElementLocated

Útil para aguardar até que uma mensagem de sucesso apareça em uma div, por exemplo. Lembrando que, para aguardar até que um texto esteja presente em um input de texto qualquer, use a ExpectedCondition “textToBePresentInElementValue“.
Frames

frameToBeAvailableAndSwitchToIt

Como o nome diz, aguarda até que o frame esteja disponível e muda para ele, dessa forma não precisamos escrever o tão odiado “driver.switchTo().frame()“.
Aguardar até que um checkbox (ou radio button) esteja habilitado

elementToBeSelected / elementSelectionStateToBe(WebElement element, true) / elementSelectionStateToBe(By locator, true)

Lembrando que é muito importante, principalmente com checkboxes, colocar uma espera como essa após o clique no elemento. Seu teste pode rodar “rápido demais” e acabar não dando tempo de selecionar o checkbox.
Aguardar até que um checkbox (ou radio button) esteja desabilitado

elementSelectionStateToBe(WebElement, false) / elementSelectionStateToBe(By locator, false)

Mesma dica que comentei acima.

Outros casos
Aplicações que usam muito AJAX
Em aplicações que usam muito AJAX, com campos muito dinâmicos, o WebDriver pode acabar “se perdendo” e lançando exceções como NoSuchElementException ou StaleElementReferenceException. O grande problema é que esses erros podem ser intermitentes, gerando falsos negativos. Testes com essa característica são chamados de flaky tests.
Passei por diversos problemas como esse ao testar aplicações que usam AJAX demais nos campos. A solução foi adicionar ignores à instância de wait, para aguardar pela condição especificada, ignorando as exceções que citamos. Além disso, acabei conhecendo e utilizando a classe FluentWait, que, segundo a API: ”é uma implementação da interface Wait que permite configurar o tempo de timeout, o intervalo de polling e adicionar ignores para exceções específicas.”
Você pode declarar uma instância de FluentWait da seguinte forma:

Wait wait = new FluentWait(driver)
.withTimeout(10, TimeUnit.SECONDS)
.pollingEvery(1, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class)
.ignoring(StaleElementReferenceException.class);

Fica fácil de ler o que código acima faz: cria uma instância de FluentWait com timeout de 10 segundos, intervalo de polling de 1 segundo, e ignorando as exceções NoSuchElementException e StaleElementReferenceException. O FluentWait é extremamente flexível e pode ser usado nas mais complexas situações.
Alan Richardson (Evil Tester), autor dos livros “Selenium Simplified” e “Java For Testers”, escreveu um post muito interessante sobre o uso do FluentWait com WebElements.

Aguardar até o valor de um atributo mudar
Em algum momento, pode surgir a necessidade de aguardar até que algum atributo de um elemento mude, por exemplo. Porém, essa prática não é muito recomendada (seção “Waiting for attributes“), então use-a com cuidado (ainda assim, é melhor do que usar Thread.sleep).
Vamos considerar o seguinte exemplo, que vivenciei recentemente:

Na imagem acima vemos dois inputs de texto (A e B) e um botão “Calcular”. Suponha que quando informo um valor no Input A e clico no botão, é feita uma requisição a um sistema externo e um valor é calculado e exibido no Input B. De acordo com as ExpectedConditions que vimos anteriormente, poderíamos, a princípio, usar a “textToBePresentInElementValue” para automatizar a espera dessa requisição, certo?
Poderíamos, mas apenas se soubéssemos exatamente qual valor seria retornado pela requisição. No caso, isso não era trivial e não era o foco do teste. Nesse teste, precisávamos apenas do Input B preenchido para prosseguir com o preenchimento de um form. Logo, bastava aguardar até que a tag “value” do Input B tivesse algum valor qualquer diferente de vazio.
A classe ExpectedCondition permite que você crie suas próprias condições customizadas. O exemplo em questão foi resolvido usando uma espera como a seguinte:

public static void aguardaAteQueValueMude(final WebElement element)
{
WebDriverWait wait = new WebDriverWait(driver, 10);

wait.until(new ExpectedCondition() {
public Boolean apply(WebDriver driver) {
String value = element.getAttribute(“value”);

if(!value.equals(“”)) {
return true;
}

return false;
}
});
}

No trecho de código acima, observe que estou criando uma ExpectedCondition booleana que, a cada intervalo de polling, vai recuperar o conteúdo da tag “value” do elemento (no caso, o Input B) e, caso esse valor seja diferente de vazio (“”), a condição retorna true. Caso contrário, após os 10 segundos de timeout, retorna false.

Para complementar, recomendo dar uma olhada nos links abaixo (alguns deles foram citados no texto). Recomendo também a palestra da Trish Khoo (Google) sobre falhas intermitentes, apresentada na Selenium Conference 2013.
Compartilhem suas dúvidas nos comentários, até o próximo post!

Referênciashttp://docs.seleniumhq.org/docs/04_webdriver_advanced.jsp
http://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/support/ui/ExpectedConditions.html
http://seleniumsimplified.com/2012/08/fluentwait-with-webelement/
http://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/support/ui/FluentWait.html
http://blog.mozilla.org/webqa/tag/webdriverwait/
http://vnrtech.blogspot.com.br/2013/04/selenium-explicit-wait.html

Source: http://stefanteixeira.com.br/2014/04/29/entendendo-os-tipos-de-esperas-no-selenium-webdriver/?utm_source=rss&utm_medium=rss&utm_campaign=entendendo-os-tipos-de-esperas-no-selenium-webdriver

Category: Java, Selenium WebDriver, Testes Automatizados

Você também pode querer ler

Comments are off for this post.