CasperJS: testes de aceitação automatizados com JavaScript

O que é o CasperJS?

O CasperJS é uma ferramenta escrita em JavaScript que permite a geração de scripts de navegação e testes para o PhantomJS.  O PhantomJS funciona como um browser headless.

O que é um headless browser?
Um headless browser é um navegador web que não possui interface gráfica. Assim, não conseguimos ver o conteúdo da página em nossa tela. Mas, mesmo sem interface gráfica, ele é capaz de executar diversas ações na página visitada: clicar em links e botões, preencher formulários etc.
Headless browsers são utilizados, comumente, para programar web crawlers e para a criação de testes automatizados (Oba! Testes automatizados!).

O CasperJS permite, dentre outras coisas:

  • Preencher e submeter dados de formulários HTML;
  • Clicar em links;
  • Capturar screenshots de páginas web;
  • Escrever suites de testes.

Assim, o CasperJS é uma ferramenta que podemos utilizar para automatizar testes de aceitação – de maneira similar ao que fazemos com o Selenium WebDriver, por exemplo.

Vantagens e desvantagens de utilizar o CasperJS

É interessante ressaltar alguns pontos que ajudam a escolher se devemos utilizar ou não o CasperJS para automatizar nossos testes.

  1. Velocidade. Os testes escritos em CasperJS costumam executar muito rápido, principalmente se compararmos com testes criados com o Selenium WebDriver. Essa característica, dentre outras coisas, advém do fato de o CasperJS rodar em um headless browser (lembrando que podemos fazer o mesmo com o Selenium utilizando, por exemplo, o HtmlUnit como driver).
  2. JavaScript. Os scripts escritos em CasperJS são feitos em JavaScript. Portanto, é necessário ter conhecimento da linguagem para conseguir escrever os casos de testes. Isso, hoje, não chega a ser problema, já que é quase um pré-requisito para boa parte dos desenvolvedores web conhecerem JavaScript. Agora, claro, se a equipe não tiver domínio da linguagem, é mais uma coisa pra aprender.
  3. Ideal para integração contínua. Como ele usa um headless browser na execução dos testes, ele não precisa de interface gráfica (diferentemente do Selenium, por exemplo, que precisa abrir um browser para executar os testes). Com isso, os scripts de testes escritos com o CasperJS rodam facilmente nos servidores de integração contínua.
  4. Headless browser. Embora o uso de um headless browser traga vantagens (como a velocidade de execução e a facilidade de execução dentro de um servidor de integração contínua), temos o problema de ele não ser um navegador de uso real dos usuários – como o Firefox, IE ou Chrome. Com isso, os testes executam em um ambiente que simula – mas não é! – o navegador onde a aplicação será efetivamente executada. Portanto, se há a necessidade de o script de teste se comportar 100% como um navegador real, o CasperJS pode não ser a escolha adequada.

Instalando o CasperJS na sua máquina

Vou utilizar, no exemplo desse post, o CasperJS integrado com o PhantomJS. Portanto, primeiramente, é necessário instalar o PhantomJS no seu ambiente.

Instalando o PhantomJS

Se você já utiliza o NPM, basta executar o comando a seguir.

npm install phantomjs -g

Para confirmar que a instalação foi realizada com sucesso, entre com o comando abaixo que deverá retornar a versão do PhantomJS instalada.

phantomjs -v

Instalando CasperJS

Depois disso, assumindo que você utiliza o NPM, basta usar o comando a seguir.

npm install casperjs -g

Para confirmar a instalação do Casper, entre com o comando abaixo que vai retornar a versão do CasperJS instalada.

casperjs --version

Pronto! Agora estamos pronto para escrever nossos casos de testes com o CasperJS. Vamos lá!

Utilizando o CasperJS para escrita de testes

Todo código aqui apresentado encontra-se disponível no meu GitHub.

Escrevi, há um tempo, um post sobre como automatizar testes de aceitação com o Selenium. Você pode acessá-lo aqui. Vou utilizar aqui o mesmo exemplo que usei naquele post: a busca de endereços por bairro do site do Correios.

Abaixo, segue a imagem do formulário dessa página.

Formulário de pesquisa do Correios de logradouro por bairro

O cenário que queremos automatizar é que, após informar os dados de pesquisa e clicar no botão “Buscar”, seja exibida uma página com a listagem de endereços, como a mostrada a seguir.

Página com resultados da busca
Página com resultados da busca

Os passos do teste, portanto, são:

  1. Acessar a página de pesquisa no site do Correios.
  2. Preencher os dados de pesquisa
  3. Clicar no botão “Buscar”.
  4. Verificar o resultado: a tabela com a listagem de endereços existe.

Vamos automatizar cada um desses passos com o CasperJS.

Acessar a página de pesquisa no site do Correios

Vamos escrever o código que acessa a página de pesquisa por logradouro do site dos Correios.

casper.test.begin("Pesquisa por endereço deve retornar resultados", 2, function(test) {

   casper.start("http://www.buscacep.correios.com.br/sistemas/buscacep/buscaLogBairro.cfm");
	
});

Em nosso script, como não poderia deixar de ser, estamos utilizando o módulo de teste do CasperJS: casper.test.

A primeira linha utiliza a função begin(). Essa função serve para inicializar uma suite de testes. Ela possui 3 argumentos: o primeiro é uma descrição dos testes; o segundo argumento (que é opcional) é a quantidade de testes (asserções) que planejamos executar; o terceiro argumento é uma função de callback que recebe uma intância do objeto Tester. É nessa função que tudo acontece.

Dentro dessa função, fazemos uma chamada ao método start(). Essa função configura e inicializa o módulo Casper e, em seguida, visita a url recebida como primeiro argumento.

Preencher os dados de pesquisa

Agora vamos preencher os dados do formulário. Vamos continuar nosso script.

casper.test.begin("Pesquisa por endereço deve retornar resultados", function(test) {

   ...

   casper.then(function() {
      casper.fill("form#Geral", {
         "UF": "RJ",
         "Localidade": "Rio de Janeiro",
         "Bairro": "Copacabana",
      }, false);
   });

});

Agora criamos um passo de navegação (navigation step) ao script de execução por meio da função then() do módulo casper.

Essa função recebe como argumento uma outra função, que contém o código do passo. Nesse caso, utilizamos a função fill(), que nos permite preencher os campos de um formulário. O primeiro argumento de fill() é o selector CSS do formulário – no caso estamos selecionado o formulário por meio de seu identificador; o segundo argumento é um objeto que contém os nomes dos campos do formulário e os valores que desejamos preencher (colocamos “RJ” no campo UF, “Rio de Janeiro” no campo Localidade e “Copacabana” no Bairro). O último atributo indica se desejamos ou não fazer o submit do formulário – optei por não fazer, por isso o valor false.

Clicar no botão “Buscar”

Abaixo está o código que clica no botão buscar.

casper.test.begin("Pesquisa por endereço deve retornar resultados", function(test) {

   ...

   casper.then(function() {
      casper.click("input[type='submit']");
   });

});

Aqui o código é simples. Criamos outro passo de navegação com a função then() e adicionamos o passo de clicar no botão com a função click() do módulo casper.

Cabe lembrar que esse passo seria desnecessário caso no passo anterior, quando preenchemos o formulário com a função fill(), passássemos true como o terceiro argumento da função; isso faria com que o formulário seja submetido após o preenchimento dos campos.

Verificando o resultado: a tabela com a listagem de endereços existe

O passo final que torna o nosso script um caso de teste é verificar se o resultado desejado foi atingido. Isso é feito por meio de asserções disponibilizadas pelo módulo de teste do CasperJS. Vamos ao código.

casper.test.begin("Pesquisa por endereço deve retornar resultados", function(test) {

   ...

   casper.then(function() {
      casper.test.assertTextExists("DADOS ENCONTRADOS COM SUCESSO.", "Texto de dados encontrados existe.");
      casper.test.assertVisible("table.tmptabela", "A tabela de resultados existe.");
   });
});

Criamos mais um passo de navegação com then() e dentro desse passo fazemos duas asserções: a primeira que verifica se o texto “DADOS ENCONTRADOS COM SUCESSO” existe na página; a segunda verifica que a tabela com a listagem de endereços está presente na página.

O código completo do teste

Abaixo está o código completo do nosso caso de teste.

casper.test.begin("Pesquisa por endereço deve retornar resultados", 2, function(test) {

 casper.start("http://www.buscacep.correios.com.br/sistemas/buscacep/buscaLogBairro.cfm");

 casper.then(function() {
    casper.fill("form#Geral", {
     "UF": "RJ",
     "Localidade": "Rio de Janeiro",
     "Bairro": "Copacabana",
    }, false);
 });

 casper.then(function() {
    casper.click("input[type='submit']");
 });

 casper.then(function() {
    casper.test.assertTextExists("DADOS ENCONTRADOS COM SUCESSO.", "Texto de dados encontrados existe.");
    casper.test.assertVisible("table.tmptabela", "A tabela de resultados existe.");
 });

 casper.run(function() {
    test.done();
 });

});

Pronto! Aí está o código completo do nosso caso de teste. A única coisa que ainda não tinha comentado é a chamada à test.done() dentro da função run().

A chamada casper.run() faz com que todos os passos criados anteriormente sejam executados. run(), opcionalmente, pode receber uma função de callback. No nosso caso, passamos esta função e chamamos test.done(). Essa chamada serve pra marcar a suite de teste como processada.

Executando o caso de teste

Executar a suite de teste é muito fácil. Basta digitar o comando a seguir.

casperjs test busca-logradouro-correios-testcase.js

Após a chamada, você deve ver uma saída como a mostrada na figura a seguir.

Execução do teste com sucesso

Para ver o teste falhando, podemos modificar o preenchimento do formulário colocando no campo “Localidade” o valor “São Paulo”. Com isso, a saída é mostrada a seguir, indicando que houve falha.

Resultado de execução com falha

Conclusão

A ideia desse post foi apresentar o CasperJS e mostrar a estrutura básica de um caso de teste feito com ele.

Como citei no post, a velocidade de execução dos testes com o CasperJS é tremenda. E é importante lembrar, também, que ele roda em cima do PhantomJS que é um headless browser, ou seja, os testes não estão rodando em cima de um navegador que o usuário realmente utiliza. Isso pode trazer alguns comportamentos diferentes daqueles que o usuário encontra.

Por fim, deixo alguns links que considero importante e que vão lhe ajudar caso deseje conhecer mais e escrever casos de teste com o CasperJS.

É isso. Quaisquer sugestões ou críticas, não hesite em deixar seu comentário abaixo.

Até a próxima.