Chrome Headless com Selenium WebDriver

Introdução

Vamos mostrar como utilizar o Selenium WebDriver com o Chrome Headless para a executar testes de aceitação automatizados web.

Ao final desse artigo você será capaz de executar o Selenium utilizando o modo headless do Chrome.

Chrome Headless: por que usar?

Como mostramos em um post anterior, os testes de aplicações web com Selenium precisam de um navegador para a execução. A comunicação entre o Selenium e os navegadores é feita por meio dos drivers – ChromeDriver, FirefoxDriver, OperaDriver etc.

Na configuração padrão, durante sua execução, o Selenium abre a interface gráfica do navegador para executar os testes. Assim conseguimos visualizar as ações sendo feitas: visita a páginas, preenchimento de campos em formulários, clique em links etc. Isso é bastante útil, inclusive, para a depuração e confirmação de que as coisas funcionam como esperado.

Já no modo headless, não é disponibilizada a interface gráfica do navegador durante a execução dos testes. É como se eles executassem em background. Esse modo é muito útil, sobretudo, para a execução dos testes em servidores de integração contínua – CI. Tipicamente, um servidor CI não possui ambiente gráfico; logo, o modo headless torna-se um requisito para a execução dos testes de aceitação automatizados nesse ambiente.

Cabe ressaltar que já tínhamos disponíveis algumas soluções de drivers que permitem a execução do Selenium em modo headless, utilizando o HtmlUnit ou o PhantomJS. No entanto, essas soluções simulam os engines dos navegadores. O Chrome Headless, por outro lado, permite a execução dos testes em um navegador real, com todas as suas funcionalidades.

Configuração Básica

Para e execução do modo headless do Chrome, faz-se necessário ter pelo menos a versão 59 no Mac ou Linux. No Windows o suporte é oferecido a partir da versão 60. Portanto, verifique a versão do seu navegador e veja se o mesmo é compatível com o modo headless.

Vamos utilizar o Selenium WebDriver em sua versão 3. Para isso, adicionamos a dependência do mesmo ao nosso projeto, conforme mostrado a seguir.

  <dependency>
	<groupId>org.seleniumhq.selenium</groupId>
	<artifactId>selenium-java</artifactId>
	<version>3.4.0</version>
	<scope>test</scope>
  </dependency>

Exemplo

Para ilustrar o uso do modo headless, vamos utilizar o mesmo exemplo apresentado no post Testes de aceitação automatizados com Selenium. Mais especificamente, o código que automatiza o preenchimento do formulário do site do Correios e que permite a busca de logradouros por bairro.

Abaixo o código, que utiliza o ChomeDriver em seu modo padrão.

@Test
public void preencheFormularioCorreiosBuscaLogradouroPorBairro() {
  WebDriver driver = new ChromeDriver();
  // Visita a página do Correios
  driver.get("http://www.buscacep.correios.com.br/sistemas/buscacep/buscaLogBairro.cfm");

  // Escolhe o valor de UF
  Select selectUF = new Select(driver.findElement(By.name("UF")));
  selectUF.selectByVisibleText("RJ");
  // Preenche a Localidade com o valor "Rio de Janeiro"
  WebElement inputLocalidade = driver.findElement(By.name("Localidade"));
  inputLocalidade.sendKeys("Rio de Janeiro");
  // Preenche o campo Bairro com o valor "Copacabana"
  WebElement inputBairro = driver.findElement(By.name("Bairro"));
  inputBairro.sendKeys("Copacabana");

  // clica no botão Buscar
  WebElement buttonBuscar = driver.findElement(By.cssSelector("input[type='submit'"));
  buttonBuscar.click();

  // verifica se há resultados
  String codigoPagina = driver.getPageSource();
  assertThat(codigoPagina, Matchers.containsString("DADOS ENCONTRADOS COM SUCESSO."));
  assertNotNull(driver.findElement(By.cssSelector("table.tmptabela")));

  driver.quit();

}

Ao executar esse código, é aberta a janela do navegador e as ações programadas são realizadas. Vamos fazer a modificação para executar esse mesmo código no modo headless.

@Test
public void preencheFormularioCorreiosBuscaLogradouroPorBairro() {
  ChromeOptions options = new ChromeOptions();
  options.addArguments("--headless");

  WebDriver driver = new ChromeDriver();
  // Visita a página do Correios
  driver.get("http://www.buscacep.correios.com.br/sistemas/buscacep/buscaLogBairro.cfm");

  // Escolhe o valor de UF
  Select selectUF = new Select(driver.findElement(By.name("UF")));
  selectUF.selectByVisibleText("RJ");
  // Preenche a Localidade com o valor "Rio de Janeiro"
  WebElement inputLocalidade = driver.findElement(By.name("Localidade"));
  inputLocalidade.sendKeys("Rio de Janeiro");
  // Preenche o campo Bairro com o valor "Copacabana"
  WebElement inputBairro = driver.findElement(By.name("Bairro"));
  inputBairro.sendKeys("Copacabana");

  // clica no botão Buscar
  WebElement buttonBuscar = driver.findElement(By.cssSelector("input[type='submit'"));
  buttonBuscar.click();

  // verifica se há resultados
  String codigoPagina = driver.getPageSource();
  assertThat(codigoPagina, Matchers.containsString("DADOS ENCONTRADOS COM SUCESSO."));
  assertNotNull(driver.findElement(By.cssSelector("table.tmptabela")));

  driver.quit();

}

Observem as linhas em destaque; essas 2 linhas de código permitem que a execução do teste seja feito no modo headless. Basicamente, antes de criar uma instância do ChromeDriver, criamos uma instância de ChromeOptions e passamos para a mesma o argumento --headless, usando o método addArguments(). Por fim, atribuimos essa option ao construtor do ChromeDriver.

Simples, não?

Conclusão

Nesse post mostramos como utilizar o Chrome Headless em conjunto com os testes escritos com o Selenium WebDriver.

O modo headless é extremamente útil para execução dos testes em servidores de integração contínua onde, de forma geral, não dispomos de interface gráfica.

Uma outra vantagem deste modo é a velocidade de execução dos testes. No exemplo apresentado, os testes em modo headless executaram, em média, 4 vezes mais rápido do que no modo padrão. Cabe ressaltar que o quão mais rápido a execução será vai depender da configuração da máquina. Mas, de maneira geral, o modo headless é mais rápido!

O código desse post está disponível aqui.