Trabalhando com testes funcionais distribuídos em Java
Neste artigo desenvolveremos testes funcionais distribuídos de uma aplicação web, ou seja, executando suíte de testes em diferentes máquinas (virtuais) em paralelo. Para isso usaremos Selenium Grid e WebDriver, bem como o TestNG e o VirtualBox.
Imagine uma aplicação web com cem testes funcionais automatizados e, ao fazermos uma alteração de funcionalidade desejamos executar os testes de regressão com o intuito de verificar se as outras não foram danificadas. Após a execução sem problemas, podemos verificar que o tempo gasto nestes foi algo em torno de seis horas. Diante disso, precisamos otimizar para reduzir o tempo de execução dos nossos testes funcionais automatizados.
Uma possível solução seria a distribuição da execução destes utilizando o Selenium GRID usando duas máquinas virtualizadas com o apoio do VirtualBox. Com essa distribuição de tarefas, o que levaria seis horas para rodar tudo passaria a gastar metade do tempo. Este artigo destaca essa solução na prática, mas com menos testes.
O Selenium WebDriver e o TestNG permitem escrever, executá-los e escolher em quais navegadores isso ocorrerá. Veremos nesse artigo como isso funciona na prática. Mas antes de iniciarmos o desenvolvimento, vamos conhecer melhor as ferramentas utilizadas.
Selenium WebDriver
É um framework de automação de testes, fornecendo uma API em diferentes linguagens, como Java, C#, Python e outros, que automatiza ações de usuário na interface web em diferentes navegadores. Ele serve para integrar o código-fonte com a tela do sistema e com o banco de dados. Sua arquitetura é apresentada na Figura 1.
Selenium Grid
Este permite distribuir os testes escritos com a API WebDriver em várias máquinas físicas ou virtuais. Além disso, o Selenium Grid tem dois conceitos importantes para o seu funcionamento:
- Hub: atua como um ponto central, ou seja, um servidor que carregará todos os testes a serem executados e distribuídos para o(s) Node(s). Recomenda-se criar apenas um único Hub para comandar;
- Node: atua como um ponto ligado ao Hub central esperando receber os testes a serem executados. Vários nodes podem ser ligados ao Hub central, mas nenhum pode se ligar a outro.
Vejamos na Figura 2 a arquitetura do Selenium Grid.
Para apoiar a qualidade do software, a família Selenium ainda conta com um IDE próprio para ajudar na execução de testes funcionais
Para esse artigo também usaremos, em conjunto com o IDE Eclipse :
- VirtualBox: É um software de virtualização de plataforma, que permite ao usuário instalar e executar sistemas operacionais independentes em um único computador.
- TestNG: É um framework de criação e execução de testes de unidade em Java;
- Apache Maven: É uma ferramenta de gestão de projetos de software que utiliza o conceito de POM (modelo de objeto de projeto) para a compilação de projetos que envolve a construção, elaboração de relatórios e documentação em uma central de informações, sendo compatível com diferentes linguagens. Mas usaremos a linguagem Java 8 para esse exemplo.
Visão geral
Desenvolveremos os testes funcionais distribuídos na aplicação web pronta que está em http://artigo.pe.hu.
Então o primeiro teste consiste em acessar na página inicial a opção “Trabalhe Conosco”, preencher todos os campos do formulário e enviá-lo. Ao final, verifica-se se o envio deu certo. O segundo consiste em entrar na página inicial e clicar na opção Conversor -> Temperatura e ao carregar a página devemos testar todas as combinações de cálculos de conversão de temperatura, verificando se todos os resultados estão corretos.
O primeiro teste será executado no Firefox da primeira máquina virtual (Ubuntu; Node 1) e o segundo no Google Chrome da segunda máquina virtual (Ubuntu; Node 2).
Para que tudo funcione seguiremos os passos a seguir:
- Configuração das máquinas i. Configuração do Hub central na nossa máquina física local utilizando o Selenium Grid;ii. Virtualização de duas máquinas com Ubuntu utilizando o VirtualBox;iii. Configuração dos Nodes nas duas máquinas virtuais, e após, ligá-las ao Hub central utilizando Selenium Grid;
- Criação de um novo projeto no Eclipse com Maven utilizando o Java 8;
- Criação das classes utilizando o Selenium WebDriver;
- Criação das classes de testes utilizando o TestNG e posterior execução dos mesmos;
Assim, a visão geral desse artigo pode ser vista na Figura 3.
Configuração das máquinas
Para começar precisamos baixar o Selenium Standalone Server .jar (vide seção Links). Para criar o hub central em nossa máquina física local executaremos o comando a seguir (use o shell ou prompt de comando, pois o comando funciona para todos os sistemas operacionais):
java -jar selenium-server-standalone-2.47.1.jar -role hub
Caso o comando não funcione, provavelmente é porque ainda não tem instalado o Java na máquina ou não configurou bem as varáveis de ambiente.
Se tudo ocorreu bem, a mensagem apresentada será semelhante à Figura 4.
Repare na linha em destaque que o Selenium Standalone Server nos forneceu o endereço, que servirá para registar os Nodes ao Hub central.
Se colocarmos no navegador o endereço http://192.168.0.6:4444/grid/console, podemos observar quais nodes estão sob controle do Hub central, além das suas configurações, como mostra a Figura 5.
Precisamos agora virtualizar duas máquinas utilizando o VirtualBox e depois fazer as configurações de Nodes nelas. Baixe ISO do VirtualBox na versão do sistema operacional da máquina local (vide seção Links), que no nosso caso é o Ubuntu em sua versão “14.10” 32 bits.
Com o programa aberto, clique em Novo e informe dentro do VirtualBox o valor “ubuntu 1” no campo nome e selecione a versão “Ubuntu (32 bits)”, como na Figura 6.
Após clicar em próximo, a tela seguinte será para informar o tamanho da memória. Como serão configuradas duas máquinas, selecione apenas ¼ da memória total e clique em “Próximo >”.
Na nova tela configuraremos o HD: certifique-se que as opções a seguir serão marcadas nas próximas telas:
- opção “Criar um disco rígido virtual agora” e clique em “Criar”;
- tipo de arquivo de disco rígido de ser o “VDI (VirtualBox Disk Image)”;
- o tipo “Armazenamento em disco rígido físico” deve ser selecionado;
- o tamanho deve ser “Tamanho Fixo”;
- para a tela de “Localização e tamanho do arquivo” deixe o mínimo recomendável, que no caso são 8 GB para o Ubuntu, em seguida clique em “Criar”.
Depois de termos criado a nossa máquina virtual, selecione-a na janela principal do VirtualBox e depois clique no menu “Configurações”. Na janela aberta selecione o item “Rede” no lado esquerdo e depois clique na aba “Adaptador 1” e, logo em seguida, na opção “Conectado a:” escolha o item “Placa em modo Bridge”, como mostra a Figura 7.
Ainda com a opção “ubuntu 1” selecionada, clique no menu de opções “Iniciar (T)” para iniciar a instalação do Ubuntu. Assim, uma janela como a Figura 8 é apresentada. Selecione o local onde está a ISO ou disco de instalação e depois clique em “Iniciar”.
Para criar a segunda máquina virtual basta repetir os mesmos passos, porém, use o nome “ubuntu 2”. Após a criação, instale o Java em ambas e os respectivos browsers, de acordo com as instruções passadas no início do artigo.
Para o Chrome, vamos baixar o driver direto do site do Selenium (vide seção Links). Vá até a seção “Third Party Drivers, Bindings, and Plugins → Browser” e clique no link chromedriver_linux32.zip. Este driver é necessário para facilitar a comunicação do navegador com o Selenium Standalone Server (Hub central). Após baixar realize a configuração com os seguintes comandos:
- No Ubuntu) e Mac OS X:
export PATH=$PATH:/caminho/para/chromedriver
- No Windows:
PATH=$PATH;\caminho\para\chromedriver
Para o Firefox não precismos baixar ou configurar nenhum driver.
Para configurar os nodes nas máquinas virtuais e ligá-las a Hub central precisamos executar um comanda Java em cada máquina virtual. Para o Node 1 execute o seguinte comando:
java -jar selenium-server-standalone-2.47.1.jar -role node -hub
http://192.168.0.6:4444/grid/register -browser browserName="firefox",
maxInstances=1,platform=LINUX
E para o Node 2 execute o comando:
java -jar selenium-server-standalone-2.47.1.jar -role node -hub
http://192.168.0.6:4444/grid/register -browser browserName="chrome",
maxInstances=1,platform=LINUX
Note que o valor “http://192.168.0.6:4444/grid/register” a frente do comando -hub se refere ao endereço do Hub central, assim fizemos o registro ao Hub central.
Repare também que no comando “-browser” definimos ao atributo -browserName o nome do navegador que estará apto para a executar os testes funcionais da aplicação web.
Ao final podemos visualizar no endereço http://192.168.0.6:4444/grid/console os Nodes que registramos, como mostra a Figura 9.
Criando o projeto
No Eclipse pressione CTRL+N e selecione o item Project Maven. Ao clicar em "Next >" uma nova janela se abrirá e nela marque o checkbox "Create a simple project" e clique em "Next"novamente. Uma nova tela aparecerá e deve ser preenchida conforme mostra a Figura 10.
Para adicionar as dependências no POM do Maven abra o pom.xml e acrescente o código da Listagem 1 entre as tags . Logo após execute o “Maven Update Project” utilizando o ALT+F5.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<!-- Versão do plugin maven -->
<version>3.3</version>
<configuration>
<!-- Versão do java -->
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<!-- Versão do selenium -->
<selenium.version>2.47.1</selenium.version>
</properties>
<dependencies>
<!-- Selenium -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>${selenium.version}</version>
<scope>test</scope>
</dependency>
<!--Driver do Selenium remoto -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-remote-driver</artifactId>
<version>${selenium.version}</version>
<scope>test</scope>
</dependency>
<!-- TestNG -->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.9.6</version>
<scope>test</scope>
</dependency>
</dependencies>
Criando as classes principais
Precisamos agora criar a estrutura de pacotes da Figura 11 em nosso projeto no diretório /projeto-maven/src/main/java.
Na Interface EstabelecerDriver.java precisamos adicionar o código da Listagem 2 para definir as propriedades que o WebDriver usará para acessar o browser. Assim, ao solicitar uma nova sessão, o cliente pode especificar o browser e a plataforma a serem usadas.
public interface EstabelecerDriver {
//Declarações de métodos
WebDriver obterObjetoWebDriver(DesiredCapabilities desiredCapabilities);
WebDriver obterObjetoWebDriverRemoto(DesiredCapabilities desiredCapabilities,
Platform plataforma, String enderecoRemoto);
DesiredCapabilities obterCapacidadesDesejadas();
}
Para o Enum TipoDriver adicionaremos o código da Listagem 3. Este servirá para definir tipos de drivers, que contém métodos úteis dos quais iremos utilizar nas classes de testes para a chamada de instâncias de WebDriver's (Firefox e Chrome).
public enum TipoDriver implements EstabelecerDriver {
FIREFOX {
public DesiredCapabilities obterCapacidadesDesejadas() {
DesiredCapabilities capabilities = DesiredCapabilities.firefox();
return capabilities;
}
public WebDriver obterObjetoWebDriver(DesiredCapabilities capabilities) {
return new FirefoxDriver(capabilities);
}
public WebDriver obterObjetoWebDriverRemoto(
DesiredCapabilities capabilities, Platform plataforma,
String enderecoRemoto) {
capabilities.setPlatform(plataforma);
WebDriver driver = null;
try {
driver = new RemoteWebDriver(new URL(enderecoRemoto),
capabilities);
} catch (MalformedURLException e) {
e.printStackTrace();
}
return driver;
}
},
CHROME {
public DesiredCapabilities obterCapacidadesDesejadas() {
DesiredCapabilities capabilities = DesiredCapabilities.chrome();
capabilities.setCapability("chrome.switches",
Arrays.asList("--no-default-browser-check"));
HashMap<String, String> chromePreferences = new HashMap<String, String>();
chromePreferences.put("profile.password_manager_enabled", "false");
capabilities.setCapability("chrome.prefs", chromePreferences);
// Fim
return capabilities;
}
public WebDriver obterObjetoWebDriver(DesiredCapabilities capabilities) {
return new ChromeDriver(capabilities);
}
public WebDriver obterObjetoWebDriverRemoto(
DesiredCapabilities capabilities, Platform plataforma,
String enderecoRemoto) {
capabilities.setPlatform(plataforma);
WebDriver driver = null;
try {
driver = new RemoteWebDriver(new URL(enderecoRemoto),
capabilities);
} catch (MalformedURLException e) {
e.printStackTrace();
}
return driver;
}
}
A seguir temos alguns detalhes importantes sobre esse código:
- Linha 5: temos o método que retorna as capacidades para usar o Firefox;
- Linha 10: temos o método que retorna uma instância do Driver do Firefox para uso;
- Linha 15: temos o método que retorna um objeto remoto;
- Linha 19: Define o sistema operacional;
- Linha 23: Atribuição da instância do objeto remoto WebDriver, com o retorno na linha 31;
- Linha 37: temos o método que retorna as capacidades para usar o Chrome;
- Linhas 40 a 47: temos neste bloco a definição de alguns comandos para o Google Chrome, pois não queremos aquela pergunta de definição do navegador padrão e nem que o gerenciador de senhas pergunte se gostaria de salvar os dados de login cada vez que um teste executar uma ação de login;
- Linha 52: método que retorna uma instância do Driver do Chrome para uso;
- Linha 56: método que retorna um objeto WebDriver remoto.
Note que ao lado do nome do Enum TipoDriver existe a definição implements EstabelecerDriver: isso quer dizer que o Enum TipoDriver está assinando um contrato com a interface EstabelecerDriver e, como consequência, irá definir todos os métodos declarados na interface. Contudo, conseguimos definir os Enums FIREFOX e CHROME, que serão úteis na criação das classes testes.
Partiremos para a criação de outro pacote com a estrutura semelhante à Figura 12 no diretório /projeto-maven/src/main/java. Este servirá para colocarmos a classe de apoio ConversorTemperatura, que conterá métodos de conversão de temperatura, úteis para as classes de testes.
Na Listagem 4 temos o código da classe ConversorTemperatura.java, que fornecerá os resultados de cálculos de conversão de temperatura.
public class ConversorTemperatura {
private final static Integer SCALE = 6;
private static Double valor = null;
public static Double aplicarScala(Double valor) {
// Atribui um BigDecimal que recebendo o valor de um Double e que ao
// final é lhe aplicado um escala
BigDecimal bd = new BigDecimal(valor).setScale(SCALE,
RoundingMode.HALF_EVEN);
// retorna o valor em Double
return bd.doubleValue();
}
// Conversão do valor de Celsius para Fahrenheit
public static String celsiusParaFahrenheit(String celsius) {
// Atribui o valor em Double convertida de uma String
valor = Double.parseDouble(celsius);
// Retorna uma String convertida de um valor Double onde lhe foi
// aplicado uma escala
return String.valueOf(aplicarScala(1.8 * valor + 32.0));
}
// Conversão do valor de Fahrenheit para Celsius
public static String fahrenheitParaCelsius(String fahrenheit) {
// Atribui o valor em Double convertida de uma String
valor = Double.parseDouble(fahrenheit);
// Retorna uma String convertida de um valor Double onde lhe foi
// aplicado uma escala
return String.valueOf(aplicarScala((5.0 * (valor - 32.0) / 9.0)));
}
}
O Método aplicarScala aplica a escala no valor Double, ou seja, o resultado do valor 51.12313121323123 ficará 51.123131, com no máximo seis dígitos após a vírgula.
Na Figura 13 vemos o novo pacote e as classes que precisamos criar no diretório /projeto-maven/src/main/java. Nessas classes incluiremos o mapeamento das páginas da aplicação web utilizando o Selenium WebDriver, bem como métodos úteis, isso porque criaremos os testes funcionais com base nelas.
A Listagem 5deve ser incluída na classe PaginaInicio e tem como objetivo fazer referência a página Início da aplicação (http://artigo.pe.hu).
public class PaginaInicio {
@FindBy(how = How.ID, using = "conversor")
private WebElement menuOpcaoConversor;
@FindBy(how = How.ID, using = "temperatura")
private WebElement menuOpcaoConversorTemperatura;
private WebDriver driver;
public PaginaInicio(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
this.driver.get("http://artigo.pe.hu");
}
public PaginaConversorTemperatura irParaPaginaConversorTemperatura() {
Actions acoesAvancadasDeUsuario = new Actions(driver);
WebDriverWait wait = new WebDriverWait(driver, 10);
acoesAvancadasDeUsuario.moveToElement(menuOpcaoConversor).perform();
wait.until(ExpectedConditions
.visibilityOf(menuOpcaoConversorTemperatura));
acoesAvancadasDeUsuario.moveToElement(menuOpcaoConversorTemperatura)
.click().perform();
return new PaginaConversorTemperatura(driver);
}
}
Na linha 2 começa o mapeamento entre o objeto WebElement com o elemento HTML que tem o id="conversor"na página web. Na linha 4 temos o mesmo tipo de mapeamento, mas com o id="temperatura".
Na linha 7 temos a implementação do construtor com a atribuição do parâmetro que tem a instância para o objeto do WebDriver corrente
O comando da linha 9 permite que os atributos mapeados nesta classe com @FindBy sejam carregados com os elementos HTML correspondentes para iniciar o navegador com o endereço web.
Na linha 14 inicializa-se o objeto Actions para uso com o WebDriver corrente, assim como a linha 15, que inicializa o objeto WebDriverWait para uso com o Webdriver corrente. No construtor da classe, além de ser definido o Webdriver, foi também definido o tempo de espera de 10 segundos. Se passar disso é lançada uma exception até que os itens do menu Conversor apareçam. Quando isso acontecer, clique no item Conversor de Temperatura.
As ações ocorrem em tempo real na aplicação web e para satisfazer o retorno do método, o objeto da classe PaginaConversorTemperatura deve ser retornado com o driver corrente.
Na classe PaginaConversorTemperatura.java precisamos incluir o código da Listagem 6, pois esta fará referência à Página Conversor de Temperatura (http://artigo.pe.hu/?pg=conv_temperatura.php).
public class PaginaConversorTemperatura {
// Mapeamento entre o objeto WebElement com o elemento html que tem o
// id="valuefromtemperature1" na página web
@FindBy(how = How.ID, using = "valuefromtemperature1")
private WebElement valorEntrada;
// Mapeamento entre o objeto WebElement com o elemento html que tem o
// id="selectfromtemperature1" na página web
@FindBy(how = How.ID, using = "selectfromtemperature1")
private WebElement webSelectDe;
// Mapeamento entre o objeto WebElement com o elemento html que tem o
// id="selecttotemperature1" na página web
@FindBy(how = How.ID, using = "selecttotemperature1")
private WebElement webSelectPara;
// Mapeamento entre o objeto WebElement com o elemento html que tem o
// id="valuetotemperature1" na página web
@FindBy(how = How.ID, using = "valuetotemperature1")
private WebElement resultado;
// WebDriver
private WebDriver driver;
// Implementação do construtor
public PaginaConversorTemperatura(WebDriver driver) {
// Atribuição do parametro que tem instância do WebDriver, para o objeto
// WebDriver que tem o escopo desta classe
this.driver = driver;
// Permite que os atributos mapeados nesta classe com @FindBy sejam
// carregados com os elementos html correspondente
PageFactory.initElements(this.driver, this);
// Carrega e inicia o navegador com o endereço web
this.driver.get("http://artigo.pe.hu/?pg=conv_temperatura.php");
}
public void preencherValorDeEntrada(String i) {
// Comando que envia valores para o elemento html
valorEntrada.sendKeys(i);
}
public WebElement obterValorDeEntrada() {
// retorna objeto WebElement
return valorEntrada;
}
public Select obterSelectDeTemperatura() {
// Retorna um objeto Select que faz referência ao elemento html Select
// na página web
return new Select(webSelectDe);
}
public Select obterSelectParaTemperatura() {
// Retorna um objeto Select que faz referência ao elemento html Select
// na página web
return new Select(webSelectPara);
}
public WebElement obterResultadoTemperatura() {
// retorna objeto WebElement
return resultado;
}
}
A classe PaginaTrabalheConosco está presente no código da Listagem 7 e tem como objetivo fazer referência a Página Trabalhe Conosco (http://artigo.pe.hu/?pg=trabalhe_conosco.php).
public class PaginaTrabalheConosco {
// Mapeamento entre o objeto WebElement com o elemento html que tem o
// id="nome" na página web
@FindBy(how = How.ID, using = "nome")
private WebElement nome;
// Mapeamento entre o objeto WebElement com o elemento html que tem o
// id="email" na página web
@FindBy(how = How.ID, using = "email")
private WebElement email;
// Mapeamento entre o objeto WebElement com o elemento html que tem o
// id="opcaoMasculino" na página web
@FindBy(how = How.ID, using = "opcaoMasculino")
private WebElement opcaoSexoMasculino;
// Mapeamento entre o objeto WebElement com o elemento html que tem o
// id="checkIngles" na página web
@FindBy(how = How.ID, using = "checkIngles")
private WebElement checkIdiomaIngles;
// Mapeamento entre o objeto WebElement com o elemento html que tem o
// id="selectOpcaoVaga" na página web
@FindBy(how = How.ID, using = "selectOpcaoVaga")
private WebElement selectOpcaoVaga;
// Mapeamento entre o objeto WebElement com o elemento html que tem o
// id="arquivoCurriculo" na página web
@FindBy(how = How.ID, using = "arquivoCurriculo")
private WebElement arquivoCurriculo;
// Mapeamento entre o objeto WebElement com o elemento html que tem o
// id="botaoEnviar" na página web
@FindBy(how = How.ID, using = "botaoEnviar")
private WebElement botaoEnviar;
// Mapeamento entre o objeto WebElement com o elemento html que tem o
// id="msgAposEnvio" na página web
@FindBy(how = How.ID, using = "msgAposEnvio")
private WebElement msgAposEnvio;
// WebDriver
private WebDriver driver;
// Implementação do construtor
public PaginaTrabalheConosco(WebDriver driver) {
// Atribuição do parametro que tem instância do WebDriver, para o objeto
// WebDriver que tem o escopo desta classe
this.driver = driver;
// Permite que os atributos mapeados nesta classe com @FindBy sejão
// carregados com os elementos html correspondente
PageFactory.initElements(this.driver, this);
// Carrega e inicia o navegador com o endereço web
this.driver.get("http://artigo.pe.hu/?pg=trabalhe_conosco.php");
}
public void preencherNome(String nomeValor) {
// Comando que envia valores para o elemento html
nome.sendKeys(nomeValor);
}
public void preencherEmail(String emailValor) {
// Comando que envia valores para o elemento html
email.sendKeys(emailValor);
}
public void marcarRadioButtonSexoMasculino() {
// Comando que clica no elemento html
opcaoSexoMasculino.click();
}
public void marcarCkeckBoxIdiomaIngles() {
// Comando que clica no elemento html
checkIdiomaIngles.click();
}
public void selecionarVaga(String vaga) {
// Atribuição de objeto Select que faz referência ao elemento html
// Select
Select selOpcaoVaga = new Select(selectOpcaoVaga);
// Comando que marca a opção do select que tem o texto x visível na
// página web
selOpcaoVaga.selectByVisibleText(vaga);
}
public void selecionarArquivoCurriculo(String urlAbsolutaDoArquivoPdf) {
// Comando que envia valores para o elemento html
arquivoCurriculo.sendKeys(urlAbsolutaDoArquivoPdf);
}
public void enviarMensagemDeTrabalheConosco() {
// Comando que clica no elemento html
botaoEnviar.click();
}
public String obterMensagemAposEnvio() {
// Comando retorna o texto visível do elemento html
return msgAposEnvio.getText();
}
}
Criação dos testes
Para os nossos testes criaremos duas classes no diretório /projeto-maven/src/test/java, conforme a estrutura vista na Figura 14.
A classe TestePaginaTrabalheConosco.java, presente na Listagem 8, irá executar os testes funcionais da página Trabalhe conosco no navegador Firefox do Node 1, então, certifique-se que o endereço da primeira máquina virtual está igual ao valor do parâmetro do método obterObjetoWebDriverRemoto(), que está dentro do método inicializarDriver() da classe TestePaginaTrabalheConosco. Lembre-se que os endereços dos Nodes podem ser visualizados em http://192.168.0.6:4444/grid/console (Selenium Standalone Server).
public class TestePaginaTrabalheConosco {
// Declaração de variável
WebDriver driver;
@BeforeClass
public void inicializarDriver() throws Exception {
// Atribuição da instância do Enum do Tipo Firefox
TipoDriver selecionadoTipoDriver = TipoDriver.FIREFOX;
// Atribuição das capacidades para usar o tipo driver Firefox
DesiredCapabilities capacidadesDesejadas = selecionadoTipoDriver
.obterCapacidadesDesejadas();
driver = selecionadoTipoDriver.obterObjetoWebDriverRemoto(
capacidadesDesejadas, Platform.LINUX,
"http://192.168.0.9:5555/wd/hub");
/**
* driver =
* selecionadoTipoDriver.obterObjetoWebDriver(capacidadesDesejadas);
*/
}
@AfterClass
public void fecharDriver() {
if (null != driver) {
driver.quit();
}
}
@Parameters({ "nomeParametro" })
// Executa o método como teste
@Test
public void testeEnviarMensagemDeTrabalheConosco(String nomeParametro) {
PaginaTrabalheConosco paginaTrabalheConosco = new PaginaTrabalheConosco(
driver);
// Preenche o campo nome
paginaTrabalheConosco.preencherNome(nomeParametro);
// Preenche o campo email
paginaTrabalheConosco.preencherEmail("brendo10x@gmail.com");
// Marca a opção do radio button
paginaTrabalheConosco.marcarRadioButtonSexoMasculino();
// Marca a opção do checkbox
paginaTrabalheConosco.marcarCkeckBoxIdiomaIngles();
// Seleciona a opção do select
paginaTrabalheConosco.selecionarVaga("Suporte de TI");
// Escolhe o arquivo pdf
paginaTrabalheConosco
.selecionarArquivoCurriculo("/home/brendo/curriculo.pdf");
// Clica no botão para enviar o formulário com as informações acima
paginaTrabalheConosco.enviarMensagemDeTrabalheConosco();
// Retorna a mensagem informada na página conversor temperatura
String msg = paginaTrabalheConosco.obterMensagemAposEnvio();
// Verifica se são iguais, o resultado com o esperado
Assert.assertEquals(msg, "Sucesso!");
}
}
No primeiro método a ser chamado na classe é anotado com @BeforeClass do TestNG. Em seguida, é atribuída a instância do Enum do Tipo Firefox e as capacidades para usar o tipo driver(Firefox).
Há a atribuição do WebDriver remoto, com as definições de que os testes funcionais desta classe serão executados no navegador Google Chrome do Node http://192.168.0.9:5555/wd/hub (1ª máquina virtual usando Linux.
Descomente o seguinte trecho de código e comente o anterior caso deseje testar esta classe no seu computador.
/**
* driver =
* selectedDriverType.obterObjetoWebDriver(desiredCapabilities);
*/
O último método fecharDriver() é executado, pois está anotado com @AfterClass do TestNG. Ele verifica se o driver é diferente null e se for, fecha o driver, ou seja o navegador que está em execução.
Na linha @Parameters({ "nomeParametro"}) temos a definição de parâmetro para que o método testeEnviarMensagemDeTrabalheConosco receba a partir do arquivo do testng.xml (do TestNG) declarado neste projeto.
Na Listagem 9 temos o código da classe TestePaginaConversorTemperatura, que irá executar os testes funcionais no navegador Google Chrome do Node 2.
public class TestePaginaConversorTemperatura {
private Select selectDe;
private Select selectPara;
private WebElement resultado;
private WebElement entrada;
private WebDriver driver;
private String resultadoValor;
private String resultadoCalculado;
@BeforeClass
public void inicializarDriver() throws Exception {
TipoDriver selecionadoTipoDriver = TipoDriver.CHROME;
DesiredCapabilities capacidadesDesejadas = selecionadoTipoDriver
.obterCapacidadesDesejadas();
driver = selecionadoTipoDriver.obterObjetoWebDriverRemoto(
capacidadesDesejadas, Platform.LINUX,
"http://192.168.0.2:5555/wd/hub");
/**
* driver =
* selecionadoTipoDriver.obterObjetoWebDriver(capacidadesDesejadas);
*/
}
@AfterClass
public void fecharDriver() {
if (null != driver) {
driver.quit();
}
}
@Parameters({ "entradaParametro" })
// Executa o método como teste
@Test
public void testeCalcularConversorTemperatura(String entradaParametro)
throws Exception {
// Este teste executa como se fosse passos de usuário
// Inicia a página inicial
PaginaInicio paginaInicio = new PaginaInicio(driver);
// Depois vai, da página inicial até a página Converso de Temperatura
PaginaConversorTemperatura paginaConversorTemperatura = paginaInicio
.irParaPaginaConversorTemperatura();
// Estando na página Conversor de temperatura
// Preencha o campo com o valor de entrada
paginaConversorTemperatura.preencherValorDeEntrada(entradaParametro);
// Atribui o valor de entrada a partir da referência do elemento html
entrada = paginaConversorTemperatura.obterValorDeEntrada();
// Atribui a referência do elemento html Select
selectDe = paginaConversorTemperatura.obterSelectDeTemperatura();
// Atribui a referência de outro elemento html Select
selectPara = paginaConversorTemperatura.obterSelectParaTemperatura();
// Por fim, atribui do valor do resultado a partir da referência do
// elemento html
resultado = paginaConversorTemperatura.obterResultadoTemperatura();
}
// Este teste só executa depois que o método
// testeCalcularConversorTemperatura executar, pois este teste depende da
// execução dele.
@Test(dependsOnMethods = { "testeCalcularConversorTemperatura" })
public void testeCelsiusParaCelsius() {
// Esses dois primeiros métodos, selecionam a opção do elemento
// html Select que tiver com x texto vísivel na aplicação web.
selectDe.selectByVisibleText("Celsius [°C]");
selectPara.selectByVisibleText("Celsius [°C]");
// Verifica se são iguais, o resultado com o esperado (valor de entrada)
Assert.assertEquals(resultado.getAttribute("value"),
entrada.getAttribute("value"));
}
// Este teste só executa depois que o método
// testeCalcularConversorTemperatura executar, pois este teste depende da
// execução dele.
@Test(dependsOnMethods = { "testeCalcularConversorTemperatura" })
public void testeCelsiusParaFahrenheit() {
// Esses dois primeiros métodos, selecionam a opção do elemento
// html Select que tiver com x texto visível na aplicação web.
selectDe.selectByVisibleText("Celsius [°C]");
selectPara.selectByVisibleText("Fahrenheit [°F]");
// Atribui o valor do atributo value do elemento html
resultadoValor = resultado.getAttribute("value");
// Atribui o resultado da conversão
resultadoCalculado = ConversorTemperatura.celsiusParaFahrenheit(entrada
.getAttribute("value"));
// Verifica se são iguais, o resultado com o esperado
Assert.assertEquals(resultadoValor, resultadoCalculado);
}
// Este teste só executa depois que o método
// testeCalcularConversorTemperatura executar, pois este teste depende da
// execução dele.
@Test(dependsOnMethods = "testeCalcularConversorTemperatura")
public void testeFahrenheitParaCelsius() {
// Esses dois primeiros métodos, selecionam a opção do elemento
// html Select que tiver com x texto vísivel na aplicação web.
selectDe.selectByVisibleText("Fahrenheit [°F]");
selectPara.selectByVisibleText("Celsius [°C]");
// Atribui o valor do atributo value do elemento html
resultadoValor = resultado.getAttribute("value");
// Atribui o resultado da conversão
resultadoCalculado = ConversorTemperatura.fahrenheitParaCelsius(entrada
.getAttribute("value"));
// Verifica se são iguais, o resultado com o esperado
Assert.assertEquals(resultadoValor, resultadoCalculado);
}
// Este teste só executa depois que o método
// testeCalcularConversorTemperatura executar, pois este teste depende da
// execução dele.
@Test(dependsOnMethods = { "testeCalcularConversorTemperatura" })
public void testeFahrenheitParafahrenheit() {
// Esses dois primeiros métodos, selecionam a opção do elemento
// html Select que tiver com x texto visível na aplicação web.
selectDe.selectByVisibleText("Fahrenheit [°F]");
selectPara.selectByVisibleText("Fahrenheit [°F]");
// Verifica se são iguais, o resultado com o esperado (valor de entrada)
Assert.assertEquals(resultado.getAttribute("value"),
entrada.getAttribute("value"));
}
Execução dos testes
Antes de executarmos os testes, certifique-se que os Nodes e o Hub central estão funcionando corretamente. Lembre-se que o TestNG deve estar instalado no seu Eclipse (vide seção Links).
Agora, termos que criar um arquivo de configuração do TestNG para dizermos a ele quais classes de testes serão executadas. Sendo assim, crie um arquivo chamado testng.xml no diretório /projeto-maven/src/test/resources e, em seguida cole o código da Listagem 10 no arquivo testng.xml.
<suite name="Suite de teste" parallel="tests" thread-count="2">
<test name="Teste na primeira máquina">
<parameter name="entradaParametro" value="2" />
<classes>
<class
name="br.com.aprendendo.selenium.testepaginas.TestePaginaConversorTemperatura" />
</classes>
</test>
<test name="Teste na segunda máquina">
<parameter name="nomeParametro" value="Brendo Felipe" />
<classes>
<class
name="br.com.aprendendo.selenium.testepaginas.TestePaginaTrabalheConosco" />
</classes>
</test>
</suite>
Observe que no arquivo criado declaramos na tag dois atributos importantes: o parallel="tests" e thread-cont="2". Isso significa que o TestNG fará o lançamento ou execução dos testes de forma paralela. Com isso, fizemos um “Aperfeiçoamento” e os testes serão iniciados e executados ao mesmo tempo, no respectivo navegador.
Neste momento, o nosso projeto já está pronto e agora vamos executar os nossos testes funcionais distribuídos. Para isso, primeiro selecione o arquivo testng.xml e em seguida clique com o botão direto e escolha as opções Run As → TestNG Suite.
Como mostra a Figura 15 todos os testes passaram. Assim, vimos na prática como agilizar os nossos testes e otimizar o desenvolvimento das nossas aplicações.
Artigos relacionados
-
Artigo
-
Artigo
-
Artigo
-
Artigo
-
Vídeo