Mudando do Selenium para o Cypress

Rossini Leite
Aurum Tech
Published in
6 min readMar 28, 2019

--

Logo que ingressei na Aurum como QA do Themis, eu recebi um legado de uma suíte de testes E2E baseada no Selenium e feita em Java. Após um período inicial para entender o padrão Page Object e adquirir o conhecimento do projeto e da linguagem, comecei a corrigir e criar testes nessa suíte.

Conforme trabalhei nessa suíte de testes, notei que estava gastando mais tempo corrigindo testes do que criando novos, além de limitações ao lidar com elementos dinâmicos e processos assíncronos, por exemplo, o select2 do framework angular js e a verificação do carregamento da página evitar de selecionar elementos ainda não renderizados.

No que tange a questão de manutenibilidade da suíte de testes;além de exigir um conhecimento mais técnico, o Selenium necessita de um caminho muito específico para selecionar um elemento, portanto, qualquer pequena alteração de layout quebra muitos testes.

Devido a essas limitações, essa suíte de testes acabou sendo abandonada e uma nova ferramenta começou a ser estudada: Cypress. Essa ferramenta surgiu principalmente para lidar com as chamadas assíncronas, características das aplicações com client-side rendering, além de ser nativa em javascript, permitindo uma maior flexibilidade na hora de trabalhar com os elementos do front-end, tornando os testes mais robustos e evitando flacky test.

Neste post apresento como instalar o Cypress, rodar os testes e as principais features que permitem lidar melhor com o comportamento assíncrono, manutenibilidade e testes de features isoladas.

Instalação

O Cypress pode ser instalado facilmente através do terminal a partir da NPM.

npm install cypress

Com a instalação concluída, tudo que separa você de utilizar o framework é abrir o terminal de comando na pasta desejada e digitar o seguinte comando.

$(npm bin)/cypress open

Toda vez que você abrir o Cypress em uma pasta vazia, ele criará um projeto default com alguns exemplos, conforme figura 1.

Figura 1- Estrutura padrão do projeto

fixtures: armazena os dados estáticos utilizados nos testes no formato json.

support: possui as funções e comandos customizados na suíte de testes.

integration: onde são criados os testes.

plugin: permite a utilização de plugins externos.

E externamente à pasta principal, um arquivo cypress.json também será criado onde permite definir as principais configurações do testes, como : url base, timeout,etc.

Além de abrir uma interface gráfica(fig. 2) onde mostra os testes disponíveis e permite rodar os testes.

Figura 2- Interface gráfica do Cypress

Rodando os testes

Os testes podem ser rodados através da interface ou através do seguinte comando executado na pasta onde está localizado o arquivo cypress.json

$(npm bin)/cypress run

Principais features

Para demonstrar alguma das features e tornar mais claro, dois arquivos de testes foram desenvolvidos para uma aplicação web, desenvolvida com propósitos educacionais. Os testes e a aplicação estão disponíveis neste repositório do github. A aplicação consiste de uma página onde é possível cadastrar transações financeiras, importá-las e apaga-las.

O primeiro arquivo de teste realiza a inserção de transações, buscando demonstrar as funcionalidades mais básicas do framework: obter elementos e assertions. O segundo arquivo testa a funcionalidade de importação de transações e mostra como realizar testes isolados através do mock de requisições.

Teste de cadastro de transações

A execução deste teste está representada pelo gif 1 e possui o código da figura 3 e 4.

Figura 3- Teste de cadastro de transações

Criação de uma transação

Ao olhar o código, nota-se muitas familiaridades com outros frameworks.

Começando pela estrutura do teste, baseado em Mocha. Percebe-se também nos assertion styles que suportam BDD(expect/should) e TDD(assert).

Outro ponto importante, principalmente em relação ao comportamento assíncrono, é a Retry-Ability. Ao analisar o código de teste(fig.3) é possível notar que há basicamente dois tipos de ação: obter o elemento DOM e validar o parâmetro especificado. O Retry-Ability é a combinação deles, ou seja, primeiro captura um elemento, em sequência o valida. Mas então você deve estar se perguntando onde que está a mágica?

O Retry-Ability permite, caso a validação não passe, tentar obter o elemento novamente até que o timeout seja alcançado.

Figura 4- Teste de cadastro de transações

Criação de várias transações

Este teste explora outras funcionalidades do framework um pouco mais elaboradas, dentre elas: fixture(linha 38), funções customizadas(linha 57) e a utilização de closures(linha 56).

Fixture

Foi utilizado para armazenar as transações, permitindo cadastrar facilmente através da interação sobre os elementos do do JSON.

Closures

O Cypress não trabalha com atribuição de variáveis, exceto em poucos casos, sendo o acesso feito através de closures, pois garante o carregamento do elemento ao acessar o seu valor. Nota-se o seu uso ao acessar os valores da fixture.

Funções customizadas

Por último, na linha 60 foi utilizada a função verificaTabela. Essa função foi criada dentro da pasta support(Figura 5) ficando disponível para qualquer teste dentro deste projeto.

Figura 5- Função customizada verificaTabela

Percebe-se no código que é possível interagir diretamente com os elementos, como usar a propriedade length, aproveitando da vantagem do framework ser nativo em js. Essa interação ajuda a tornar o teste mais dinâmico e robusto.

Teste de importação de transações

O Cypress foi desenvolvido com o intuito para não apenas lidar com o comportamento assíncrono das aplicações client-side-rendering, mas também permitir testar cada feature de maneira mais isolada possível.

Por exemplo, testar a renderização das transações na tabela(gif 2). O pré-requisito é o cadastro dessas transações, podendo ser através da inserção manual ou importando através de uma requisição.

Ambas as alternativas utilizam outras partes do sistema, podendo interferir no teste. Portanto, como é possível testar de maneira mais isolada cada feature do sistema?

Neste caso o cypress permite mockar requisições xhr e sua resposta, tornando o teste mais isolado e possível, mesmo que a url requerida esteja indisponível.

Figura 4 — Teste de importação de transações.

A figura 4 apresenta o código do teste acima. Destaca-se o trecho da linha 22–27.

Para simular uma requisição(cy.route()) é necessário inicialmente inicializar o server(cy.server()). Além disso, também exige-se o tipo de requisição, endereço e a resposta desejada.

Portanto , toda vez que a requisição for requisitada pela aplicação, o mock será acionado e retornará a resposta desejada.

Conclusão

Após começar esse processo de mudança de framework, notei que os testes estão mais estáveis e há uma flexibilidade maior na criação dos testes. Contudo o início foi um pouco vagaroso, pois a estrutura dos testes e do próprio projeto difere bastante do padrão page Object utilizado anteriormente com o Selenium.

O Cypress oferta ainda várias funcionalidades não abordadas, mas espero com este post ter mostrado algumas das suas principais features, mostrando como você poderá realizar testes E2E e lidar com os comportamentos assíncronos da sua aplicação.

Segue o link do site oficial do Cypress e do repositório com os testes utilizados, respectivamente.

https://www.cypress.io/

https://github.com/RossiniM/Selenium2Cypress

--

--