Automação de Testes Web com Selenium e WebDriver em Java

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:

  1. O script de teste (Cliente) inicia uma sessão através do ChromeDriverService, que atua como um servidor local.
  2. Este serviço expõe uma API REST local (geralmente em localhost com uma porta dinâmica).
  3. O cliente envia requisições HTTP (padrão W3C WebDriver) para o driver, que retorna um sessionId para manter o estado da sessão.
  4. O driver traduz as requisições HTTP em comandos nativos do navegador e os executa.
  5. 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");

Tags: Selenium WebDriver java automacao-de-testes webdrivermanager

Publicado em 7-15 21:21