É 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