Desenvolvimento

21 out, 2014

Testando aplicações AngularJS com Protractor

Publicidade

É sempre importante fazer testes, e melhor ainda se podemos fazer os testes antes (TDD) e, em algumas situações, até mesmo escrever uma especificação executável, a chamada “documentação viva” do BDD (Behavior-driven development). Mas quando falamos de escrever os testes antes, podemos falar tanto de testes unitários (unit tests), como de testes e2e (end-to-end).

Neste artigo, a ideia é falar de testes do tipo e2e, os quais se propõem à automação da utilização da aplicação como se fosse um usuário final interagindo com ela em fluxos do início ao fim, como o processo de login, o preenchimento e envio de um formulário de contato, a simples visita a uma página e muitos outros.

Nem sempre os testes serão utilizados como documentação para pessoas não técnicas, como se propõe a prática do BDD, portanto nem sempre precisam ser escritos nesse formato, mesmo quando estão sendo utilizados para testes de regressão, os quais se propõem a garantir que funcionalidades que já estavam funcionando não quebraram durante a entrada de novas funcionalidades, melhorias ou correções de bugs.

No caso em que o teste não precisa ser uma documentação que venha a ser lida pelo cliente, ou uma pessoa não técnica, ele pode ser somente código, e se puder ser na linguagem que a equipe de desenvolvimento está acostumada, melhor ainda!

Meu foco aqui será no uso do Protractor, ferramenta para criação de testes e2e (em JS) para aplicações AngularJS.

Para instalar o Protractor em um ambiente Unix-based (no meu caso Mac OS X Maverick), utilize o comando demonstrado abaixo:

ATENÇÃO: Para realizar a instalação do Protractor é necessário que o NodeJS esteja instalado, e que essa instalação não tenha sido realizada com permissão de super usuário (sudo). Além disso, é necessário que o Java Development Kit (JDK) esteja instalado.

$ npm install -g protractor

Esse comando irá instalar o Protractor e o webdriver-manager.

Para verificar que o Protractor foi corretamente instalado, verifique a versão instalada, utilizando o comando abaixo:

$ protractor --version

Logo depois, será necessário atualizar o webdriver-manager, que irá prover um selenium server rodando para dirigir o browser. Execute o comando abaixo:

$ webdriver-manager update

E então inicialize o servidor com o comando abaixo em um console o qual ficará rodando:

$ webdriver-manager start

Com o selenium server rodando, você está pronto para iniciar a criação de seu primeiro teste com o Protractor.

Inicialmente, vamos criar uma pasta para guardar nossos testes. Dentro da pasta do projeto, crie uma pasta tests (ou utilize o nome que você preferir). Nessa pasta, estarão localizados os dois arquivos essenciais para a execução de testes com o Protractor: o arquivo de configuração e o arquivo com os testes propriamente ditos.

Logo após, crie os arquivos conf.js e spec.js e salve-os na pasta tests criada.

Edite o arquivo conf.js no seu editor preferido (utilizei o Atom), e inclua a seguinte configuração (esse arquivo especifica onde o selenium server estará rodando, e qual arquivo com a especificação dos testes será utilizado):

// conf.js
exports.config = {
seleniumAddress: 'http://localhost:4444/wd/hub',
specs: ['spec.js']
}

Para fins de um teste experimental, iremos utilizar uma aplicação AngularJS de exemplo, que se chama todomvc. Abra o arquivo spec.js criado e cole o seguinte código:

// spec.js
describe('angularjs todo mvc homepage', function() {  
  it('should have a title', function() {
    browser.get`('http://todomvc.com/architecture-examples/angularjs/#/');

    expect(browser.getTitle()).toEqual('AngularJS • TodoMVC');
   });
});

Executando de dentro da pasta tests o comando abaixo, com o *selenium server* rodando, você terá seu primeiro teste rodando (e passando)!

protractor conf.js  
$ protractor conf.js
Using the selenium server at http://localhost:4444/wd/hub  
.
Finished in 2.416 seconds  
1 test, 1 assertion, 0 failures`

Agora, vamos interagir um pouco mais com a aplicação, visto que, nesse primeiro teste somente acessamos a URL da aplicação exemplo e verificamos seu título.

O plano agora é interagirmos com o campo de texto da aplicação, para simular um usuário real digitando neste campo. Edite do arquivo spec.js, e adicione o seguinte teste:

it('should be able to type a text in the text field', function() {  
  element(by.id('new-todo')).sendKeys('Teste de digitação em campo texto');
})

Execute novamente e verá seu novo teste rodando (e passando também!):

Finished in 5.956 seconds  
2 tests, 2 assertions, 0 failures`

Agora vamos evoluir o teste criado acima para que, após a digitação do texto no campo, ele seja submetido e então seu resultado seja verificado. Podemos fazer isso da seguinte forma: edite o arquivo spec.js, e modifique o teste criado acima, refatorado assim:

it('should be able to type a text in the text field, press enter, and verify the result', function() {

  var todoTextField = element(by.id('new-todo'));
  var todoLabel = element(by.className('ng-binding'));
  var text = 'Teste de digitação em campo texto'

  todoTextField.sendKeys(text);
  todoTextField.sendKeys(protractor.Key.ENTER);

  expect(todoLabel.getText()).toEqual(text);
});

Após a execução do novo teste (refatorado), você deve perceber um aumento no tempo de execução, devido aos novos passos adicionados a ele.

Finished in 6.974 seconds  
2 tests, 2 assertions, 0 failures

Por fim, vamos deletar o registro criado no cenário acima após a submissão do campo texto, e validar que ele não está mais disponível na lista. Veja o código abaixo.

it('should clean the items from the list and verify that no items are available in the list',function() {

  var toogleAllCheckBox = element(by.id('toggle-all'));
  var clearCompletedButton = element(by.id('clear-completed'));
  var viewDiv = element(by.className('view'));

  toogleAllCheckBox.click();
  clearCompletedButton.click();

  expect(viewDiv.isPresent()).toBe(false);
});

 

Finished in 7.547 seconds  
3 tests, 3 assertions, 0 failures

Pronto! Você já tem o conhecimento básico necessário para iniciar a criação de testes de sua aplicação AngularJS, utilizando o Protractor, e tendo a facilidade de desenvolver a aplicação como um todo, na mesma linguagem, inclusive nos testes.

Você também pode acessar no GitHub os arquivos gerados no desenvolvimento deste artigo.

Referência: Protractor