API Selenide: Desenvolvimento de testes funcionais em Java

Veja neste artigo como trabalhar com a API Selenide para o desenvolvimento de testes funcionais de aplicações web.

Atualmente o Selenium WebDriver é uma das ferramentas mais populares para o desenvolvimento de testes de funcionais de aplicações web, pois é fácil de usar e bastante flexível. No entanto, uma equipe de desenvolvimento web localizada na Estónia chamada Codeborne percebeu que ao usar o Selenium WebDriver teriam que escrever o mesmo código nos testes, por exemplo, tinham que inicializar e fechar o navegador a cada teste e outras duplicações desnecessárias. Assim, a equipe Codeborne desenvolveu uma API para retirar o código repetitivo, dando origem ao Selenide, que será o objeto de estudo desse artigo. Acompanharemos por essa introdução como essa API funciona para criar testes funcionais junto da linguagem Java.

Conhecendo o Selenide

O Selenide é uma API baseada no Selenium WebDriver para o desenvolvimento de testes funcionais web em Java, oferecendo uma ótima sintaxe para a escrita de testes, fácil de aprender e usar. A API resolve todos os problemas típicos, como testes de aplicações web modernas com Ajax e abstrai para o desenvolvedor o uso do WebDriver e as configurações do Selenium. Além disso, ele fornece métodos adicionais simples que o Selenium, por “default”, não oferece, como manipular radiobutton, drop-down, captura de tela e limpar o cache do navegador.

Nas próximas seções aprenderemos na prática sobre o Selenide e seus principais aspectos.

Criando e configurando o projeto

Para iniciarmos o desenvolvimento com Selenide utilizaremos o Eclipse, Maven e o JUnit. Para começar inicie o Eclipse e em seguida vá até File > New> Other ... e Maven > Maven Project. Clique em Next e na seguinte tela marque o checkbox Create a simple project e clique em Next novamente. Na janela que aparece, como na Figura 1, preencha os campos Group Id ", Artifact Id e em Packaging clique emwar.

Figura 1. Janela do Eclipse com as configurações do projeto Maven

Depois de criado o projeto precisamos fazer alguns ajustes: o primeiro deles é configurar o pom.xml do nosso projeto acrescentando o código da Listagem 1 entre as tags e no pom.xml.

<dependencies> <!-- Selenide --> <dependency> <groupId>com.codeborne</groupId> <artifactId>selenide</artifactId> <version>2.23</version> <scope>test</scope> </dependency> <!-- JUnit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies> <!-- Build deste projeto Maven --> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <!-- Versão do plugin compiler do Maven --> <version>3.3</version> <configuration> <!-- Versão do Java --> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build>
Listagem 1. Código do arquivo pom.xml

Por fim, como o nosso projeto é uma aplicação web, precisamos gerar um arquivo de configuração chamado web.xml. Para isso vá até o o projeto maven e clique duas vezes. Em seguida clique com o botão direito no item “Deployment Descriptor: ” e logo depois clique em “Generate Deployment Descriptor Stub”. Selecione o projeto novamente e execute o Maven Update Project utilizando o Alt+F5 ou com o botão direito do mouse escolhendo a opção “Maven > Update Project”. Assim o nosso projeto já está configurado.

Trabalhando com seletores de elementos

Para o desenvolvimento de testes funcionais com Selenide precisamos entender como funciona a seleção de elementos (HTML) para que possamos realizar a automação de teste interagindo com esses elementos em uma interface web.

O Selenide fornece comandos simples e úteis para realizar esta tarefa. A seguir serão apresentados os comandos semelhantes à do jQuery para escolher os elementos (HTML) com Selenide:

E para trabalhar junto com os métodos anteriores o Selenide oferente métodos (static) utilitários que facilitam a seleção de elementos:

Faremos agora um exemplo prático utilizando os seletores de elementos do Selenide. Para isso, primeiramente vá ao diretório “ /src/main/webapp e nele crie um arquivo chamado seletores.html acrescentando o código da Listagem 2. É neste arquivo que conterá elementos HTML que serão úteis para os nossos testes com seletores do Selenide.

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Trabalhando com seletores de elementos</title> </head> <body> <div id="texto">Obter elemento com o id: texto</div> <a title="Meu título">Obter elemento com o title: Meu título</a> <form id="idFormulario"> <input name="nomeInput" type="text" value="Obter elemento pelo atributo value" /> </form> </body> </html>
Listagem 2. Código do arquivo seletores.html

Em seguida, criaremos a nossa classe de testes que irá testar os elementos da listagem anterior. Para isso vá ao diretório /src/test/java e nele crie um pacote chamado “testes” e dentro deste crie uma classe chamada TesteSeletorElemento acrescentando o código da Listagem 3.

package testes; import static com.codeborne.selenide.Selectors.*; import static com.codeborne.selenide.Selenide.*; import static org.junit.Assert.assertEquals; import org.junit.*; import org.openqa.selenium.By; public class TesteSeletorElemento { @Before public void abreAPaginaParaTeste() { open("http://localhost:8080/aprendendo-selenide/seletores.html"); } @Test public void testeSeletorElementoSelenideElement() { assertEquals("<div id=\"texto\">Obter elemento com o id: texto</div>", $(By.id("texto")).toString()); assertEquals("<input name=\"nomeInput\" type=\"text\" value=\"Obter elemento pelo atributo value\"></input>", $(By.name("nomeInput")).toString()); assertEquals("<div id=\"texto\">Obter elemento com o id: texto</div>", $("#texto").toString()); assertEquals("<div id=\"texto\">Obter elemento com o id: texto</div>", $(byText("Obter elemento com o id: texto")).toString()); assertEquals("<div id=\"texto\">Obter elemento com o id: texto</div>", $(withText("Obter elemento com o id: texto")).toString()); assertEquals("<div id=\"texto\">Obter elemento com o id: texto</div>", $(by("id", "texto")).toString()); assertEquals("<input name=\"nomeInput\" type=\"text\" value=\"Obter elemento pelo atributo value\"></input>", $(by("value", "Obter elemento pelo atributo value")).toString()); assertEquals("<a title=\"Meu título\" >Obter elemento com o title: Meu título</a>", $(by("title", "Meu título")).toString()); assertEquals("<a title=\"Meu título >Obter elemento com o title: Meu título</a>", $(byTitle("Meu título")).toString()); assertEquals("<input name=\"nomeInput\" type=\"text\" value=\"Obter elemento pelo atributo value\"></input>", $(byValue("Obter elemento pelo atributo value")).toString()); } @Test public void testeSeletorElementosElementsCollection() { assertEquals("[\n <form id=\"idFormulario\"></form>\n]", $(By.id("idFormulario")).toString()); assertEquals("[\n <form id=\"idFormulario\"></form>\n]", $(by("id", "idFormulario")).toString()); } }
Listagem 3. Código da classe o TesteSeletorElemento.java

Observe que nossa classe de teste possui dois testes contendo afirmações que irão comparar se os elementos esperados são iguais aos elementos da Listagem 2 com o auxílio dos seletores do Selenide. É um exemplo simples apenas para fixar o uso dos seletores que iremos utilizar em exemplos concretos ou do mundo real ainda neste artigo. Para executar o nosso primeiro teste, antes teremos que publicar nossa aplicação tornando acessível para o Selenide, utilizando para isso o Tomcat 8.

Realizado o deploy da aplicação iremos agora executar os nossos testes, para isso selecione a classe de teste TesteSeletorElemento e depois clique com o botão direito do mouse para a opção “Run As > JUnit Test”. Por padrão, o Selenide irá executar os testes funcionais no navegador Firefox.

Se tudo ocorreu como esperado teremos o resultado semelhante à Figura 2.

Figura 2. Resultado dos testes com seletores de elementos (html) do Selenide

Trabalhando com SelenideElement

A interface SelenideElement nada mais é do que um wrapper do Selenium WebDriver que o Selenide aprimorou trazendo para sua API e que agora fornece métodos adicionais facilitando o trabalho do engenheiro de teste no desenvolvimento de testes funcionais automatizados. A seguir serão apresentados alguns dos principais métodos adicionais dessa interface:

Agora faremos um exemplo utilizando os métodos adicionais do Selenide apresentados anteriormente. Para isso, no diretório /src/main/webapp crie um arquivo chamado selenideElement.html acrescentando o código da Listagem 4. É neste arquivo que conterá um formulário HTML que será útil para os nossos testes com métodos adicionais do Selenide.

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Trabalhando com SelenideElement</title> </head> <body> <form id="formulario"> <fieldset> <legend>Trabalhe Conosco</legend> <label for="input-1">Nome:</label> <input type="text" placeholder="Informe seu nome" name="nome" /> <br> <label>Sexo:</label> <input type="radio" name="sexo" value="Masculino">Masculino <input type="radio" name="sexo" value="Feminino">Feminino<br> <label >Idioma:</label> <input type="checkbox" name="idioma" value="Inglês">Inglês <input type="checkbox" name="idioma" value="Espanhol">Espanhol<br> <label>Vaga:</label> <select id="vaga"> <option value="Desenvolvedor">Desenvolvedor</option> <option value="Gerente de TI">Gerente de TI</option> <option value="Suporte de TI">Suporte de TI</option> </select> <br> <input type="submit" value="Enviar" id="btnEnviar" /> <input type="submit" value="Cancelar" id="btnCancelar" /> </fieldset> </form> </body> </html>
Listagem 4. Código do arquivo selenideElement.html

Na sequência criaremos uma classe de testes que irá testar os elementos da listagem anterior. Para isso no diretório “ /src/test/java crie uma classe chamada TesteSelenideElement acrescentando o código da Listagem 5.

package testes; import static com.codeborne.selenide.Condition.visible; import static com.codeborne.selenide.Selectors.by; import static com.codeborne.selenide.Selenide.*; import static org.junit.Assert.assertEquals; import org.junit.Before; import org.junit.Test; import org.openqa.selenium.By; public class TesteSelenideElement { @Before public void abreAPaginaParaTeste() { open("http://localhost:8080/aprendendo-selenide/selenideElement.html"); } @Test public void teste() { $("#btnEnviar").should(visible); $("#btnCancelar").shouldNot(visible); $(By.name("nome")).setValue("Brendo Felipe"); selectRadio(By.name("sexo"), "Masculino"); $(by("value", "Inglês")).click(); $(By.id("vaga")).selectOptionByValue("Suporte de TI"); assertEquals("Brendo Felipe", $(By.name("nome")).val()); assertEquals(true, $("#btnEnviar").exists()); assertEquals(false, $("#btnCancelar").isDisplayed()); assertEquals("Masculino", getSelectedRadio(By.name("sexo")).val()); assertEquals("Inglês", $(By.name("idioma")).val()); assertEquals("Suporte de TI", $(By.id("vaga")).getSelectedValue()); $("#btnEnviar").pressEnter(); } }
Listagem 5. Código da classe TesteSelenideElement.java

Note que no código escrevemos um teste que realiza o preenchimento de um formulário e isso verifica aspectos dos campos utilizando os métodos adicionais do Selenide. Após publicada novamente a nossa aplicação web com a Listagem 4 iremos executar os nossos testes. Para isso selecione a classe de teste TesteSelenideElement e depois clique com o botão direito na opção Run As > JUnit Test.

Se tudo ocorreu como esperado teremos o resultado igual à Figura 3.

Figura 3. Resultado dos testes com os métodos adicionais do Selenide

Trabalhando com Condições

Atualmente muitas aplicações web usam AJAX para mudar partes do site de forma dinâmica, assim quando escrevemos testes funcionais com este efeito precisamos definir o tempo de espera até que o elemento desejado apareça. Para isso, o Selenide fornece uma classe chamada Condition que , ao contrário de Selenium WebDriver, o Selenide aguarda por algum tempo limite pré-definido.

Por padrão, o tempo limite do Selenide para aguardar é de quatro segundos, mas pode ser configurado via propriedade selenide.timeout. Além disso, a classe Condition também é usada para testar uma página verificando o estado em que estão os elementos HTML, por exemplo, verificar se input x está visível ou não, e outras verificações. Vejamos alguns atributos e métodos principais da classe Condition:

Faremos agora um exemplo prático utilizando a classe Condition com seus métodos e atributos apresentados anteriormente. Para isso, primeiramente no diretório /src/main/webapp crie um arquivo chamado condition.html acrescentando o código da Listagem 6. É neste arquivo onde conterá elementos HTML que serão úteis para os nossos testes.

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Trabalhando com Condições</title> </head> <body> <form id="meuFormulario"> <label for="nome" >Nome:</label> <input type="text" id="nome" value="Brendão" readonly="readonly" name="nome"><br/> <label for="email" >Email:</label> <input type="email" autofocus="autofocus" id="email" > </form> <div class="estilo_rodape" id="rodape"></div> <p id="meuParagrafo">Meu texto</p> </body> </html>
Listagem 6. Código do arquivo condition.html

Em seguida criaremos a nossa classe de testes que irá testar os elementos da Listagem 6. Para isso, no diretório “ /src/test/java crie uma classe chamada TesteCondition acrescentando o código da Listagem 7.

package testes; import static com.codeborne.selenide.Condition.*; import static com.codeborne.selenide.Selenide.*; import org.junit.Before; import org.junit.Test; import org.openqa.selenium.By; public class TesteCondition { @Before public void abreAPaginaParaTeste() { open("http://localhost:8080/aprendendo-selenide/condition.html"); } @Test public void testeConditionFormulario(){ $(By.id("meuFormulario")).should(visible); $(By.id("meuFormulario")).should(exist); $(By.id("meuFormulario")).shouldNot(hidden); $(By.id("nome")).should(readonly); $(By.id("nome")).should(attribute("value")); $(By.id("nome")).should(name("nome")); $(By.id("nome")).should(value("Brendão")); $(By.id("nome")).should(type("text")); $(By.id("nome")).should(id("nome")); $(By.id("rodape")).should(empty); $(By.id("rodape")).should(cssClass("estilo_rodape")); $(By.id("email")).should(focused); $(By.id("email")).should(enabled); $(By.id("email")).shouldNot(disabled); $(By.id("meuParagrafo")).should(textCaseSensitive("Meu texto")); } }
Listagem 7. Código da classe TesteCondition.java

Note que no código escrevemos um teste que irá realizar a verificação ou checagem em determinados elementos HTML utilizando a classe Condition do Selenide.

Observe um trecho de código retirado da Listagem 7:

$(By.id("nome")).should(name("nome"))

Estamos fazendo uma verificação em um elemento HTML que tem o id=”nome” testando se o mesmo possui um atributo name com o valor nome: se sim o teste passa, senão o teste falha.

Não deixe de fazer o deploy da aplicação com o novo código conforme a Listagem 6.

Iremos agora executar o nosso teste e para isso escolheremos a classe de teste TesteCondition. Depois clique com o botão direito do mouse na opção Run As > JUnit Test e se tudo ocorreu como esperado teremos o resultado igual à Figura 4.

Figura 4. Resultado dos testes com seletores de elementos do Selenide

Trabalhando com Coleção de Elementos

Uma página HTML é constituída por vários elementos, como tabelas com várias linhas, múltiplas opções para um elemento selecionado, grupos de radiobuttons, diferentes tipos de listas, dentre outros. Então, para o desenvolvimento de testes funcionais vamos precisar de uma construção que nos permita executar operações em vários elementos e o Selenide fornece maneiras úteis para trabalhar com coleções de elementos, como é a chamada a classe ElementsCollection. A seguir serão apresentados os métodos que esta classe oferece para trabalhar:

Na Listagem 8 temos um exemplo utilizando os métodos da classe ElementsCollection apresentados. Para isso, no diretório /src/main/webapp crie um arquivo chamado elementsCollection.html adicionando o código apresentado a seguir, pois é neste arquivo que conterá uma tabela HTML útil para os nossos testes.

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Trabalhando com Coleção de Elementos</title> </head> <body> <table border="1" id="tblGastosMensais" > <caption>Gastos mensais</caption> <tr> <th>Mês</th> <th>Gasto (R$)</th> </tr> <tr> <td>Janeiro</td> <td>R$250</td> </tr> <tr> <td>Fevereiro</td> <td>R$500</td> </tr> </table> </body> </html>
Listagem 8. Código do arquivo elementsCollection.html

Na sequência criaremos uma classe de teste que irá testar os elementos da listagem anterior. Para isso, no diretório /src/test/java crie uma classe chamada TesteElementsCollection acrescentando o código da Listagem 9.

package testes; import static com.codeborne.selenide.CollectionCondition.size; import static com.codeborne.selenide.Condition.text; import static com.codeborne.selenide.Selenide.*; import static org.junit.Assert.*; import org.junit.Before; import org.junit.Test; public class TesteElementsCollection { @Before public void abreAPaginaParaTeste() { open("http://localhost:8080/aprendendo-selenide/elementsCollection.html"); } @Test public void testeTabelaGastosMensais() { $("#tblGastosMensais tr").shouldHave(size(3)); assertEquals(true, $("#tblGastosMensais tr td").findBy(text("R$500")).exists()); assertEquals(false, $("#tblGastosMensais tr td").filterBy(text("Janeiro")).isEmpty()); assertEquals(false, $("#tblGastosMensais tr td").excludeWith(text("Fevereiro")).isEmpty()); } }
Listagem 9. Código da classe TesteElementsCollection.java

Note que na classe apresentada escrevemos um teste que irá verificar alguns aspectos dos elementos HTML de uma tabela com o auxílio da classe ElementsCollection. Observe o seguinte trecho de código retirado da listagem anterior:

$("#tblGastosMensais tr").shouldHave(size(3))

Com este código verificamos se o elemento #tblGastosMensais tr tem a quantidade de linhas tr igual a três: se sim o teste passa, senão o teste falha.

Após realizado o deploy da aplicação com o novo código da Listagem 8 iremos executar os nossos testes. Para isso, na classe de teste TesteElementsCollection clique com o botão direito selecionando a opção Run As > JUnitTest. Se tudo ocorreu como esperado teremos o resultado igual à Figura 5.

Figura 5. Resultado do teste utilizando a classe TesteElementsCollection

Trabalhando com ScreenShooter

Sabemos que durante a execução dos testes poderão ocorrer falhas e quando ocorrem gostaríamos de ter o máximo de informações para encontrar o mais rápido possível a razão da falha na aplicação. Com isso, o Selenide nos dá uma ajuda realizando um ScreenShooter da janela do navegador em caso de falha durante os testes. Além disso ele captura a página HTML, facilitando a depuração.

Para trabalhar com ScreenShooter do Selenide vamos automatizar um teste web que consiste em efetuar uma busca no Google e, a partir desse resultado, verificar se um determinado texto existe na primeira página. Contudo, para que o Selenide execute o ScreenShooter da página precisamos forçar a falha do teste.

Para criarmos este teste primeiro escolha o diretório “ /src/test/java e nele crie uma classe chamada TestePaginaBuscaNoGoogle adicionando o código da Listagem 10.

package testes; import static com.codeborne.selenide.CollectionCondition.texts; import static com.codeborne.selenide.Selenide.*; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import com.codeborne.selenide.junit.ScreenShooter; public class TestePaginaBuscaNoGoogle { @Rule public final ScreenShooter makeScreenshotOnFailure = ScreenShooter.failedTests(); @Before public void abreAPaginaParaTeste() { open("https://www.google.com.br/"); } @Test public void testeScreenShooterComFalha() throws InterruptedException { $("#lst-ib").val("Brendo Felipe").pressEnter(); $("#search").shouldHave(texts("Brendo Felipe | Facebook tal")); } }
Listagem 10. Código da classe TestePaginaBuscaNoGoogle.java

Note que no código podemos destacar a seguinte instrução Java:

@Rule public final ScreenShooter makeScreenshotOnFailure = screenShooter.failedTests();
Listagem 1. NOME

Com esta instrução dizemos que durante a execução dos testes, se algum teste encontrar falha, o Selenide imediatamente executa um ScreenShooter da página web contendo a falha detectada.

Agora iremos executar o teste com a classe TestePaginaBuscaNoGoogle e depois clicando com o botão direito do mouse na opção Run As > JUnit Test. Se tudo ocorreu como esperado teremos o resultado igual à Figura 6.

Figura 6. Resultado do teste

Com o resultado do teste forçando a falha, veremos agora o ScreenShooter do Selenide. Para isso atualize o projeto (apertando F5). Com isso, conseguimos visualizar o ScreenShooter gerado pelo Selenide que está presente no seguinte diretório: \build\reports\tests\testes\TestePaginaBuscaNoGoogle\testeScreenShooterComFalha.

Veja que o Selenide mostrou-se ser uma excelente ferramenta para automatizar testes funcionais em Java.

Artigos relacionados