🎯 Boas práticas em automação de testes com Cypress
A automação de testes é uma parte essencial do desenvolvimento de software moderno, permitindo validar funcionalidades, detectar regressões e garantir a qualidade das aplicações de forma eficiente. O Cypress 🚀 é uma das ferramentas mais populares para automação de testes end-to-end, proporcionando uma experiência moderna, rápida e confiável para testar aplicações web.
Este documento aborda as boas práticas para escrever testes eficazes com Cypress, garantindo que os testes sejam rápidos, legíveis, reutilizáveis e confiáveis. Além disso, são apresentadas estratégias para evitar testes frágeis e melhorar a manutenção dos testes ao longo do tempo. 🛠️
Por que seguir boas práticas? 🤔
Aplicar boas práticas na automação de testes com Cypress traz diversos benefícios, como:
- Redução do tempo de execução ⏳: Testes otimizados executam mais rápido, evitando atrasos nos pipelines de CI/CD.
- Maior confiabilidade ✅: Evita falsos positivos e negativos, garantindo que os testes falhem apenas quando há problemas reais na aplicação.
- Facilidade de manutenção 🔄: Um código bem estruturado é mais fácil de entender, modificar e reaproveitar.
- Melhor legibilidade 📖: Testes bem escritos ajudam toda a equipe a entender o comportamento esperado da aplicação.
Ao longo deste documento, veremos práticas recomendadas para estruturar e otimizar testes no Cypress, cobrindo desde a configuração inicial até técnicas avançadas para aumentar a eficiência dos testes automatizados. 🔍
Boas práticas em automação de testes com Cypress
- Documentação oficial
- Vídeo Completo
- Mapa mental Cypress
- Vídeo palestra criador Cypress Completo
- Vídeo palestra criador Cypress (parte específica de boas práticas)
Pular navegação entre as telas (quando possível)
Links
Vídeo; Documentação Oficial (Custom Commands, tópico 4)
Exemplo: Caso o interesse seja validar se uma tela está disponível corretamente após um cadastro ou login de usuário, não é ideal gastar tempo da aplicação preenchendo o respectivo formulário. Para isso, é uma boa prática pular a etapa de navegar pela tela de cadastro/login realizando um processo como, por exemplo, uma requisição HTTP que envie diretamente à aplicação um cadastro/login teste que possibilite a verificação da tela desejada.
Definir uma URL base global
Links
Serve para facilitar o reuso do código, evitando repetições de, por exemplo, o comando cy.visit(‘https://aplicacao.com’)
quando quiser acessar a aplicação, ou até mesmo ter que digitar toda a URL da aplicação quando quiser acessar uma sub rota (cy.visit(‘https://aplicacao.com/rota/subrota’)
).
Com uma URL global, o código necessário para acessar a aplicação se torna apenas cy.visit(‘/’)
, ou, em casos de sub rotas, cy.visit(‘/rota/subrota’)
.
A URL base pode ser definida através do arquivo cypress.config.js
ou um arquivo de constantes.
const { defineConfig } = require('cypress')
module.exports = defineConfig({
e2e: {
baseUrl: 'http://localhost:8484',
},
})
Usar múltiplas asserções (Específico E2E)
Links
Vídeo; Documentação Oficial; Documentação Oficial (Core Concepts)
No Cypress, as asserções são verificações usadas para garantir que o código ou aplicação está funcionando conforme esperado durante os testes. Elas servem para comparar valores ou condições e confirmar se o estado atual de um elemento ou funcionalidade corresponde ao comportamento esperado. Existem dois tipos principais de asserções no Cypress:
Asserções Implícitas
O Cypress automaticamente inclui asserções enquanto você interage com elementos. Por exemplo, se for usado um comando como .should()
, ele verifica se algo atende a uma condição.
Asserções Explícitas
Usam bibliotecas como Chai (inclusa no Cypress) para criar verificações mais personalizadas. Essas asserções podem ser combinadas com o Cypress para verificar diretamente os valores.
Exemplos de Condições Comuns:
- Existência:
.should('exist')
ou.should('not.exist')
- Visibilidade:
.should('be.visible')
ou.should('not.be.visible')
- Estado de um elemento:
.should('be.disabled')
,.should('be.checked')
- Texto ou conteúdo:
.should('contain', 'Texto')
,.should('have.text', 'Texto exato')
- Classes ou atributos:
.should('have.class', 'nome-classe')
,.should('have.attr', 'atributo', 'valor')
Como em um teste E2E a quantidade de features avaliadas é maior e mais diversificada que em testes unitários, usar múltiplas asserções permite um teste mais seguro e maior facilidade para encontrar a falha do teste. Evitar, nesses casos, criar um teste para cada feature, e, ao invés disso, criar um teste com várias asserções.
Escrever cenários com boa legibilidade
Links
Pensar no nome e contexto do teste com base em 4 passos:
- O que está sendo testado? (describe - context)
- Sob que circunstâncias, condições?
- Qual o resultado esperado?
- Juntar resposta da 2 e 3 em uma frase para descrever o teste.
Exemplo:
- Aplicação - Feed
- Autenticado
- Visualizar o menu navegável
-
context(‘Feed’, () => {
it(‘Quando estiver autenticado, devo visualizar o menu navegável’, () => {...
})
})
Seguir convenção AAA no fluxo de teste
Links
O que é?
É uma forma de pensar nos nossos testes em formato de blocos:
- Arrange - Preparação: O que é preciso fazer antes de executar o teste ou para chegar ao ponto para de fato testar a aplicação.
- Act - Ação: O que o teste vai executar para conferir os resultados
- Assert - Asserção/ Validação / Verificação: Onde é conferido se o teste teve o resultado esperado
Exemplo:
- Arrange: Preparando o teste através da interceptação da requisição HTTP e da realização do login no sistema
beforeEach(() => {
// ARRANGE
// interceptar uma requisição
cy.intercept({
method: 'GET',
hostname: 'res.cloudinary.com'
}, {
statusCode: 200,
fixture: 'example'
})
cy.login()
});
- Act: A ação de acessar a URL do site com uma baseURL já definida
it('Quando estiver autenticado, devo visualizar o menu navegável', () => {
// ACT
cy.visit('/')
})
- Asserts que verificarão se o menu navegável está visível e se ele contém o que é exigido nas regras de negócio
it('Quando estiver autenticado, devo visualizar o menu navegável', () => {
// ACT
cy.visit('/')
// ASSERT
cy.get('nav ul li')
.should('be.visible')
.and('have.length', 6)
.each(($el, index, $list) => {
let options = [
'Home',
'Explore',
'Notifications',
'Bookmarks',
'Profile',
'More'
]
cy.log(index)
cy.get($el)
.find('span')
.should('have.text', options[index])
})
})
Isolar fatores externos (quando necessário)
Links
Na validação da aplicação, pode ser que haja requisições a serviços externos, como serviços de imagens, o que poderia acarretar em falsos negativos, ou seja, um teste que falha por alguma falha de terceiros, e não uma falha da execução da aplicação.
Documentar comandos customizados
Links
Vídeo; Documentação Oficial; Repositório Exemplo Oficial
O Cypress conta com um recurso para criar comandos customizados ou sobrescrever comandos do Cypress para a própria API. Criar um arquivo index.d.ts
para realizar a documentação.