Refatorando testes com Protractor JS
…e testando aplicações não-AngularJS!
No primeiro post sobre o Protractor foram apresentados os comandos para instalação da ferramenta, configuração de ambiente e algumas características básicas de seu uso.
Hoje, a ideia é ir um pouco além, criando novos testes, refatorando os testes já criados e, de sobra, aprendendo como automatizar testes de aplicações não-AngularJS com o Protractor.
Até então os seguintes testes foram criados:
it('should have a title'…
it('should be able to type a text in the text field, press enter, and verify the result'…
it('should clean the items from the list and verify that no items are available in the list'…
Agora será criado um teste que marca como completos os itens da to do list e os verifica na completed view.
it('should be able to complete items and verify them in the completed list', function() {
var text = 'Criar teste para completed list';
var completedLink = element.all(by.css('a[ng-class="{selected: status == \'completed\'}"')).last();
var toggleAll = element(by.id('toggle-all'));
var completedList = element(by.css('#todo-list .completed .view .ng-binding'));
completedLink.click();
expect(completedList.getText()).toContain(text);
No teste acima, entre as linhas 3 e 7, um item é adicionado a to do list. Na linha 9 o link completed é identificado e armazenado em uma variável. Na linha 10 o elemento para marcar todos os itens da lista como completos também é identificado e armazenado em uma variável. Na linha 11 a view somente com itens completos é identificada e armazenada em uma variável. E nas linhas 13, 14 e 15 o elemento para marcar todos itens como completos é clicado, o link para a view completed é clicado e a verificação do item nesta view é realizada, nesta ordem.
Porém, olhando para o código de um dos testes já criados ("it should be able to type a text in the text field, press enter, and verify the result") e comparando-o com o novo teste, percebe-se que algum código começa a ser duplicado, especificamente, a inserção de um item na to do list.
E quando o código começa a ficar duplicado é a hora de refatorar, pois código duplicado é anti-pattern.
Com os helpers é possível isolar a lógica de testes que se repetem ao longo da bateria e tornar a legibilidade e manutenção dos testes mais serena.
Abaixo é exibido o helper para inserção de itens à lista:
it('should add an item into the todo list', function() {
Neste helper é possível notar que um módulo é exportado, o qual executa uma função que basicamente testa a inserção de um item à lista, recebendo este item como argumento.
E para se utilizar deste helper no arquivo spec.js, o seguinte código é adicionado antes do describe:
var todomvcHelper = require('./todomvc.helper');
E os testes "it should be able to type a text in the text field, press enter, and verify the result" e "should be able to complete items and verify them in the completed list" são refatorados conforme:
todomvcHelper.addTodoItem('Teste de digitação em campo texto');
it('should be able to add items in the to do list', function() {
var todoLabel = element(by.css('.view .ng-binding'));
todomvcHelper.addTodoItem('Criar teste para completed list');
it('should be able to complete items and then add them to the completed list', function() {
Com a refatoração acima, 8 linhas de código se transformaram em apenas 2 no arquivo spec.js.
helpers ajudam! =p
O código gerado até aqui já está disponível no GitHub.
Utilização do protractor para aplicações não-AngularJS
Testando aplicação Ember.JS com Protractor
A aplicação todomvc utilizada para a criação deste e o do primeiro post foi o todomvc.
Porém, este mesmo todomvc está disponível em outros frameworks, dentre eles o Ember.js.
Portanto, a ideia aqui é simplesmente refatorar os mesmos testes para que sejam executados na versão em Ember do todomvc.
Primeiro, a seguinte linha será adicionada no início de cada um dos cenários de teste criados (inclusive no helper):
Com isto já será possível rodar os testes, e alguns deles já devem passar (aqueles que não utilizam características específicas doAngularJS).
Porém, dois testes irão falhar, os quais utilizam o ng-binding, específico do AngularJS.
Para que os mesmos passem, refatore-os conforme:
var todoLabel = element(by.css('#todo-list li label'));
var completedLink = element(by.css('.selected'));
var completedList = element(by.css('#todo-list .completed label'));
Pronto! Os mesmos cenários de teste agora também irão passar quando disparados contra o todomvc em Ember.