Gerenciamento de Drivers e Configuração Inicial
A execução de testes automatizados em aplicações web exige a interação com um navegador real. Para que o código Java consiga controlar o navegador, é necessário um driver específico (como o ChromeDriver ou GeckoDriver), que atua como uma ponte de comunicação. O WebDriverManager é uma biblioteca que automatiza o download, a configuração e a manutenção desses binários, eliminando a necessidade de gerenciá-los manualmente.
Dependências do Projeto
Para iniciar, adicione as bibliotecas do WebDriverManager e do Selenium ao seu arquivo pom.xml:
<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<version>5.8.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.18.0</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.15.1</version>
</dependency>
Arquitetura e Fluxo de Comunicação
O ecossistema Selenium opera através de uma arquitetura cliente-servidor baseada em HTTP:
- O script de teste (Cliente) inicia uma sessão através do
ChromeDriverService, que atua como um servidor local. - Este serviço expõe uma API REST local (geralmente em
localhostcom uma porta dinâmica). - O cliente envia requisições HTTP (padrão W3C WebDriver) para o driver, que retorna um
sessionIdpara manter o estado da sessão. - O driver traduz as requisições HTTP em comandos nativos do navegador e os executa.
- O resultado da execução no DOM do navegador é empacotado e devolvido ao script de teste via resposta HTTP.
Exemplo Prático de Automação
Abaixo, um fluxo completo de inicialização, navegação, interação e encerramento do navegador:
public void executarFluxoDePesquisa() {
// Configuração automática do binário do Chrome
WebDriverManager.chromedriver().setup();
ChromeOptions opcoes = new ChromeOptions();
opcoes.addArguments("--incognito", "--disable-notifications");
WebDriver navegador = new ChromeDriver(opcoes);
try {
navegador.get("https://duckduckgo.com/");
WebElement campoBusca = navegador.findElement(By.cssSelector("input[name='q']"));
campoBusca.sendKeys("Engenharia de Software e Testes");
WebElement botaoPesquisar = navegador.findElement(By.cssSelector("button[type='submit']"));
botaoPesquisar.click();
} finally {
navegador.quit();
}
}
Estratégias de Localização de Elementos
A precisão na localização de nós no DOM é o pilar da automação web. As abordagens mais robustas são CSS Selectors e XPath.
CSS Selectors
Utiliza a sintaxe de folhas de estilo para buscar elemantos. É geralmente mais rápido e legível.
- ID:
#botao-enviar - Classe:
.input-padrao - Atributo:
input[type='password'] - Descendente:
form.login-box button.submit
XPath
Linguagem de consulta para documentos XML/HTML, ideal para navegação complexa na árvore DOM.
- Todos os nós:
//* - Filtro por atributo:
//input[@name='email'] - Navegação para o pai:
//span[@class='erro']/.. - Busca por texto (contém):
//button[contains(text(), 'Confirmar')] - Índice de nó:
//ul[@id='menu']/li[2]
Interação e Manipulação de Elementos
Após localizar um elemento, o Selenium fornece métodos para simular ações do usuário e extrair dados:
// Interação de clique e submissão
navegador.findElement(By.cssSelector(".btn-salvar")).click();
// Limpeza e inserção de texto
WebElement campoUsuario = navegador.findElement(By.id("user"));
campoUsuario.clear();
campoUsuario.sendKeys("admin_sistema");
// Extração de informações do DOM e da página
String textoBotao = navegador.findElement(By.tagName("h1")).getText();
String tituloAba = navegador.getTitle();
String urlAtual = navegador.getCurrentUrl();
Gerenciamento de Janelas e Abas
Cada janela ou aba aberta pelo navegador possui um identificador único chamado Window Handle. Para interagir com uma nova aba aberta por um link, é necessário migrar o foco do driver.
String janelaPrincipal = navegador.getWindowHandle();
Set<String> handlesDisponiveis = navegador.getWindowHandles();
// Utilizando Stream API para encontrar e alternar para a nova janela
handlesDisponiveis.stream()
.filter(handle -> !handle.equals(janelaPrincipal))
.findFirst()
.ifPresent(novaAba -> navegador.switchTo().window(novaAba));
// Redimensionamento e Maximização
navegador.manage().window().maximize();
navegador.manage().window().setSize(new Dimension(1366, 768));
// Fechamento de janela específica (o driver precisa ser realocado se a janela principal for fechada)
navegador.close();
Captura de Evidências (Screenshots)
File imagemTemporaria = ((TakesScreenshot) navegador).getScreenshotAs(OutputType.FILE);
String caminhoDestino = String.format("./evidencias/falha_teste_%d.png", System.currentTimeMillis());
FileUtils.copyFile(imagemTemporaria, new File(caminhoDestino));
Mecanismos de Sincronização (Esperas)
Como a execução do código Java é exponencialmente mais rápida que a renderização do navegador, mecanismos de espera são cruciais para evitar NoSuchElementException.
Espera Estática (Thread.sleep)
Pausa a thread atual por um tempo fixo. Desencorajada em ambientes de CI/CD devido à imprevisibilidade e desperdício de tempo de execução.
Espera Implícita
Define um tempo limite global para que o driver aguarde a presença de qualquer elemento no DOM antes de lançar uma exceção.
navegador.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
Espera Explícita (WebDriverWait)
Aplica condições específicas (ExpectedConditions) para elementos individuais, sendo a abordagem mais robusta e recomendada.
WebDriverWait espera = new WebDriverWait(navegador, Duration.ofSeconds(15));
WebElement painelCarregado = espera.until(
ExpectedConditions.visibilityOfElementLocated(By.cssSelector(".dashboard-panel"))
);
Navegação, Alertas e Upload de Arquivos
Controle de Histórico
navegador.navigate().to("https://portal.example.com");
navegador.navigate().back();
navegador.navigate().forward();
navegador.navigate().refresh();
Tratamento de Alertas Nativos (JavaScript)
Alertas, confirmações e prompts do sistema operacional do navegador não fazem parte do DOM HTML e exigem a interface Alert.
Alert popup = navegador.switchTo().alert();
String mensagem = popup.getText();
popup.sendKeys("Texto para o prompt");
popup.accept(); // Equivalente a clicar em "OK"
// popup.dismiss(); // Equivalente a clicar em "Cancelar"
Upload de Arquivos
Como o Selenium não interage com janelas nativas do sistema opercaional (como o Windows Explorer), o upload é realizado enviando o caminho absoluto do arquivo diretamnete para a tag <input type="file">.
WebElement areaUpload = navegador.findElement(By.cssSelector("input[type='file']"));
areaUpload.sendKeys("C:\\Users\\QA\\Documents\\planilha_dados.csv");