Enquanto estamos automatizando testes, sabemos que uma boa prática dentro de um time ágil é realizar a escrita de cenários por N motivos, os quais não vou detalhar aqui, pois não é o objetivo desse artigo. Mas, como – por padrão – o Protractor não vem configurado, temos que fazer alguns ajustes no arquivo de configuração para conseguir tirar proveito de todas as vantagens que a escrita de cenários de testes nos dá, juntamente com o Cucumber.
Precisamos que o Cucumber esteja instalado na sua máquina.
npm install -g cucumber
A primeira configuração que precisamos fazer é ter a dependência do Cucumber no arquivo package.json. E para instalá-la, execute o comando abaixo dentro do diretório do seu projeto:
npm install --save-dev protractor-cucumber-framework
Vamos instalar também uma dependência para a geração do report:
npm install cucumber-html-reporter --save-dev
Vamos adicionar as seguintes configurações dentro do arquivo protractor.conf.js.
Primeiro informamos que vamos utilizar um framework customizado:
framework: 'custom', frameworkPath: require.resolve('protractor-cucumber-framework'),
Depois informamos o caminho que vão ficar as nossas features:
specs: [ 'features/*.feature ]
O caminho onde vão ficar as implementações dos steps:
cucumberOpts: { require: [ 'features/step_definitions/*.step.js', ], format: ['json:results.json', 'pretty'], profile: false, 'no-source': true,
E ainda a geração do Report dos testes:
afterLaunch: function() { var reporter = require('cucumber-html-reporter'); var options = { theme: 'bootstrap', jsonFile: 'results.json', output: 'e2e/tests_result/cucumber_report.html', reportSuiteAsScenarios: true, launchReport: true }; reporter.generate(options); },
O arquivo de configuração completo pode ser encontrado aqui. Com isso feito, já podemos iniciar nossos testes utilizando Cucumber e, para exemplificar, vamos utilizar uma aplicação simples de listagem de Pokémons. Você pode acessar a listagem aqui.
Agora vamos escrever nosso primeiro cenário.
Crie o features/busca.pokemon.feature:
#language: pt Funcionalidade: Busca de pokémons Cenário: Pesquisa de pelo nome do pokémon Dado que eu estou na tela de listagem de pokémons Quando eu digito "mew" no campo de pesquisa Então devo visualizar dois pokémons no resultado
Agora vamos executar o comando:
protractor cucumber-example/protractor.conf
O Cucumber vai gerar os steps que precisam ser implementados:
this.Given(/^que eu estou na tela de listagem de pokémons$/, function (callback) { // Write code here that turns the phrase above into concrete actions callback(null, 'pending'); }); this.When(/^eu digito "([^"]*)" no campo de pesquisa$/, function (args1, callback) { // Write code here that turns the phrase above into concrete actions callback(null, 'pending'); }); this.Then(/^devo visualizar dois pokémons no resultado$/, function (args1, callback) { // Write code here that turns the phrase above into concrete actions callback(null, 'pending'); });
Agora precisamos implementar esses steps em ações concretas, mas para isso, é preciso criar um arquivo chamado busca.pokemon.step.js dentro de features/step_definitions/. Dentro desse arquivo crie a seguinte função:
module.exports = function(){ }
Dentro dela, cole os snippets gerados.
Veja abaixo o resultado final do arquivo busca.pokemon.step.js já com as implementações necessárias:
const chai = require('chai'); const chaiAsPromised = require('chai-as-promised'); const ListagemPage = require('../../../pages/listagem.po.js'); chai.use(chaiAsPromised); const expect = chai.expect; module.exports = function(){ const listagemPage = new ListagemPage(); this.Given(/^que eu estou na tela de listagem de pokémons$/, function (callback) { listagemPage.visit().then(callback); }); this.When(/^eu digito "([^"]*)" no campo de pesquisa$/, function (nome, callback) { const filtro = listagemPage.filtro; const EC = protractor.ExpectedConditions; browser.wait(EC.presenceOf(filtro)); listagemPage.pesquisarPokemon(nome).then(callback); }); this.Then(/^devo visulizar dois pokémons no resultado$/, function (callback) { expect(listagemPage.resultados.count()).to.eventually.equal(2).and.notify(callback); }); }
Inicialmente importamos os módulos do chai.js, biblioteca de assertions que lida de forma bem completa com a questão das Promises do Protractor. Fizemos também o import de nosso PageObject (veja o primeiro artigo no qual falo sobre a utilização de PageObject).
Alguns detalhes que são importantes:
- Função de callback: Todos steps gerados possuem uma função de callback, que nada mais é do que um “link” para o próximo passo;
- Timeout: Em algumas situações, precisamos especificar um timeout para os steps. Nesse exemplo, especificamente, não foi necessário, mas para adicionar um, basta passarmos mais um parâmetro dentro do step.
Fica dessa forma:
this.Given(/^que eu estou na tela de listagem de pokémons$/, {timeout: 60 * 1000} , function (callback) { listagemPage.visit().then(callback); });
- Promise: Todos os métodos do nosso PageObject precisam retornar algo para que possamos tirar proveito do encadeamento dos steps:
listagemPage.visit().then(callback);
Esse then(callback); está informando que o próximo step só vai ser executado após o método visit do nosso PageObject ser finalizado. Caso contrário você vai ter uma dor de cabeça terrível, pois se não fizer isso, quando estiver rodando o teste em todos os passos, os steps vão informar que já foram executados sem ainda terem sido, por causa da execução assíncrona.
- Chai: Utilizar o Chai.js para fazer as validações é uma ótima escolha, pois ele é simples de ser utilizado e possui uma boa documentação com muita flexibilidade. Repare que em nosso Then, utilizamos o expect:
expect(listagemPage.resultados.count()).to.eventually.equal(2).and.notify(callback);
Esse notify(callback) vai apenas informar que os testes terminaram.
Agora que aprendemos como utilizar o CucumberJS com o Protractor, recomendo que utilizem essa forma de documentação viva e todos seus benefícios. Dessa forma, o seu time – do PO aos Devs – vão ter um guia de utilização de cada funcionalidade, o que ajudará muito à todos no dia a dia.
Espero que tenham gostado e até a próxima!
Referências
***
Este artigo foi publicado originalmente em: https://www.concrete.com.br/2018/02/01/integrando-protractor-com-cucumberjs/