Front End

17 out, 2014

Testes funcionais com CasperJS

Publicidade

Independente da ferramenta usada, os testes funcionais são imprescindíveis para manter a saúde de uma aplicação, pois com eles é possível simular o comportamento de um usuário interagindo diretamente com a regra de negócio.

Os testes funcionais não devem substituir outros, como os unitários. Eles devem complementar o conjunto e dar ainda mais cobertura. Alguns pontos interessantes:

  • Diminui consideravelmente o risco de bugs surpresas: É muito comum alterações em uma parte do software afetar outras, estes bugs muitas vezes só são descobertos pelo usuário. Fazer testes funcionais de partes críticas diminui este risco, pois podemos testar todo o sistema em cada funcionalidade inserida.
  • Aumento de produtividade: Algumas funcionalidades requerem muitos testes durante seu desenvolvimento, com ferramentas podemos automatizar o processo e evitar testes manuais.
  • Melhora a qualidade das entregas: Diminuindo o risco de bugs, as novas versões do sistema terão mais segurança e qualidade, pois dependendo do nível de profundidade dos testes é possível garantir que as funcionalidades testadas se comportam como o esperado.

Colocando a mão na massa

Principalmente no desenvolvimento de software, o tempo é muito valioso, portanto não podemos usar uma ferramenta que torne o trabalho cansativo, chato ou que dificulte a manutenção. Os testes devem ser aliados dos programadores, e o CasperJS pode atender muito bem as expectativas.

Instalação

O CasperJS é uma ferramenta feita em Javascript para o PhantomJS, e é muito simples de ser instalada – no site, além da documentação está o processo de instalação.

Mas se você possui o gerenciador de pacotes NPM, basta seguir os seguintes passos:

npm install -g phantomjs
npm install -g casperjs

Após instalar, ao digitar “casperjs” deverá ser mostrado na linha de comando um help de utilização.

Após a instalação, vamos para o primeiro exemplo: fazer um script que visita duas páginas e imprime o título:

//test.js
var casper = require('casper').create();
 
casper.start('http://viniciuswebdev.com/', function() {
    this.echo(this.getTitle());
});
 
casper.thenOpen('http://google.com', function() {
    this.echo(this.getTitle());
});
casper.run();

O then do método thenOpen significa que o script precisa esperar o método anterior terminar para então partir para o próximo passo – e faz todo sentido, pois este é o fluxo de navegação. Como cada página tem um tempo de carregamento diferente, o CasperJS precisa deste mecanismo para controlar o fluxo de execução.

Agora, vamos ver o resultado:

$ casperjs test.js 
Vinicius Oliveira | blog
Google

O CasperJS, já vem integrado com um módulo de testes com uma API muito familiar. Vamos construir um teste para visitar uma página e checar se o título dela é o esperado:

casper.test.begin('Google Visit Test', 1, 
    function suite(test) {
    
        casper.start("http://www.google.com.br");
    
        casper.then(function () {
            test.assertEquals(
              'Google', 
              this.getTitle(), 
              "Should get page title"
            );
        });
 
        casper.run(function(){
            casper.test.done();
        });
    }
);

A saída será:

$ casperjs test .
Test file: test.js                             
# Google Visit Test
PASS Should get page title
PASS 1 test executed in 3.033s, 1 passed, 0 failed, 0 dubious, 0 skipped.

Veja que nomeando os testes, é possível ter um feedback visual bem útil.

Agora vamos lidar com formulários com um teste de login, vamos testar dois possíveis resultados de uma autenticação (a falha e o sucesso). Veja que o código do teste fica bem idiomático:

casper.test.begin('Login Test', 2, function suite(test) {
    
    var siteUrl = 'https://www.example.com.br/login'
 
    //Abrimos a conexão
    casper.start(siteUrl);
 
    //Preenchemos o formulário, o último parâmetro faz 
    //o método submeter após preencher
    casper.then(function () {
        casper.fill('#form', {
            'username' : 'vinicius',
            'password' : 'abc123'
        }, true);
    });
 
    //Buscamos o elemento .alert e checamos o texto,
    // a primeira autenticação deve falhar
    casper.then(function () {
        casper.each(this.getElementsInfo('.alert'), 
            function (casper, element, j) {
                test.assertEquals(
                    element['text'], 
                    "Bad Credentials!", 
                    "Authentication shoud fail"
                );
        });
    });
 
    //Preenchemos com as credenciais corretas
    casper.then(function () {
        casper.fill('#form', {
            'username' : 'vinicius',
            'password' : 'mypassword'
        }, true);
    });
 
    //Buscamos o elemento .alert e checamos o texto, 
    //esta autenticação deve passar
    casper.then(function () {
        casper.each(this.getElementsInfo('.alert'), 
            function (casper, element, j) {
                test.assertEquals(
                    element['text'], 
                    "Welcome!", 
                    "Authentication should pass"
                );
        });
    });
 
    casper.run(function(){
        casper.test.done();
    });
});

Então vejamos a saída:

$ casperjs test .
Test file: test.js                             
# Login Test
PASS Authentication shoud fail
PASS Authentication should pass
PASS 2 tests executed in 9.389s, 2 passed, 0 failed, 0 dubious, 0 skipped.

Você pode rodar os testes com a opção –xunit=report.xml, ela vai gerar o resultados dos testes no formato xunit, portanto você pode automatizar os testes no seu servidor de integração contínua como desejar.

Todo desenvolvedor Web está familiarizado com Javascript, portanto pode ser bem rápido desenvolver usando o CasperJS, mas o ideal é testar as ferramentas disponíveis e escolher qual atende melhor as necessidades da aplicação e da equipe, e o mais importante, que viabilize a cobertura de testes nas partes importantes da aplicação.