O documento discute boas práticas para criar testes automatizados rápidos e robustos com Cypress, como fazer autenticação de forma programática, usar atributos data-* para selecionar elementos e não depender de aplicações externas. Também aborda problemas como testes lentos e instáveis.
2. Sobre mim
Meu nome é Walmyr Filho, sou um engenheiro
de software especializado em automação de
testes e integração contínua, embaixador do
Cypress.io, autor do blog TAT e do canal TAT,
instrutor de cursos de automação de testes
web no Udemy, mentor e um cara apaixonado
por skateboarding, comida vegana, música,
tatuagens e minha família.
3. O problema dos testes lentos
Testes instáveis (flaky)
Boas práticas p/ testes rápidos e confiáveis
Mão-na-massa
Perguntas e respostas
Surpresa!
Agenda
Pontos de discussão
4. Testes leeentos
E os problemas que eles trazem junto consigo
ATRASAM O TIME
Gosto de um pipeline de
integração contínua de não mais
que 10 minutos. Mais que isso e
problemas começam a voltar
quando são mais caros de
corrigir.
ATRASAM ENTREGAS OU
COMPROMETEM A QUALIDADE
É arriscado entregar um software
sem a garantia de que todos os
testes de regressão estão
passando. Mas e quando são
muito lentos uai?
SÃO "LARGADOS DE ΜÃO"
É isso mesmo, testes que
atrasam o time não são uma
alternativa para times em busca
de agilidade.
5. Testes instáveis
(os famosos flakey tests)
EXECUÇÃO 1
Ô trem bão!
Passou!
EXECUÇÃO2
E nenhum código mudou desde a
última execução.
Falhou ) :
EXECUÇÃO4
Uai, aquela falha devia ser alguma
instabilidade no ambiente.
Passou!
EXECUÇÃO 5
Vixe, esse trem é flaky!
Falhou :(
EXECUÇÃO3
E nenhum código mudou desde a
última execução de novo.
Passou!
6. Faça autenticação de forma programática
Boas práticas
Testes devem ser independentes uns dos outros
Crie mecanismos para o controle do estado da app
Selecione elementos com atributos data-*
Não tente armazenar comandos do Cypress em variáveis
Testes não devem ser muito pequenos nem muito grandes
Não teste aplicações que você não controla
Não use os hooks after e afterEach
Não use cy.wait(Number)
Inicialize o servidor antes de iniciar os testes
7. Boas práticas - continuação
Configure uma URL base (baseUrl)
Já que sobrou espaçao, fica o convite para conhecerem a playlist
Explorando a Cypress RWA no canal Talking About Testing no YouTube.
https://bit.ly/3iOeykQ
8. Testes independentes
Além disso, testes independentes facilitam na
paralelizacão de sua execução.
Testes automatizados devem ser capazes de
serem executados de forma isolada, sem a
necesidade de que outro teste tenha executado
para criar algum estado na aplicação em teste.
A falha em um teste não deve impactar no
resultados de outros testes.
Dica: utilize o hook beforeEach quando
precisar executar passos repetidos para todos
os testes de um determinado describe ou
context.
9. Autenticação
programática
Ao adiconar mecanismos para realizar login de
forma programática, os testes ficam mais rápidos
e independentes.
Realizar login via interface gráfica de usuário
como pré-condição de todos testes é custoso (em
termos de tempo de execução), além de tornar os
testes dependentes, o que por si só já é uma má
prática.
Um botão de login desabilitado por uma erro de
HMTL, por exemplo, não deveria quebrar toda
uma suíte de testes.
10. Mecanismos
para criação de estado
Alguns exemplos desses mecanismos são:
chamadas de API para criação de recursos;
comunicação com o banco de dados via tasks; ou
a execução de scripts à nível de sistema
operacional.
Ao criar tais mecanismos, garantimos testes
completamente desacoplados uns dos outros,
não precisamos de abstrações que adicionam
complexidade aos testes, tais como Page
Objects, por exemplo, e garantimos testes
rápidos e direto-ao-ponto.
11. Atributos data-*
Adicionando atributos aos elementos do
frontend, tais como: data-test, data-testid, ou
data-cy, adicionamos o que chamo de
"testabilidade" na aplicação, visto que tais
atributos são especificamente criados para fins
de testes, diminuindo a chance de mudanças no
frontend quebraem os testes.
12. Não faça isso:
var el = cy.get('seletor')
cy.get('@myBtn).click()
Lembre-se. Cypress não é Selenium!
O Cypress possui uma arquitura própria, onde
apesar de em muitos casos permitir a escrita de
código que parece síncrono, mesmo que seja
assíncrono (visto que coloca cada comando em
uma fila para posterior execução), não é possível
fazer algo como:
const myBtn = cy.contains('button', 'My button')
myBtn.click()
Porém, você pode fazer:
cy.contains('button', 'My button').as('myBtn)
13. Não teste aplicações
externas
Para garantir que tais serviços estão de acordo
com sua aplicação, você pode ter uma suite de
smoke-test, por exemplo, ou testes de contrato.
Depender do login do Google via GUI para seus
testes, ou de alguma API de terceiros pode tornar
seus testes instáveis, visto que mudanças nestes
serviços (os quais você não controla) irão quebrar
seus testes, mesmo que esteja tudo certo do "do
seu lado".
14. Testes muito pequenos
ou muito grandes
Porém, cuidado com testes muuuito grandes.
Quem sabe estes estão testando muitas coisas
não relacionadas e poderiam ser quebrados em
testes menores.
Testes end-to-end não são testes de unidade.
Devido ao seu custo de execução, vale a pena
adicionar mais de uma verificação por teste, para
otimizar seu tempo.
15. Não use os hooks
after e afterEach
Como boa prática, faça qualquer limpeza antes
da execução dos testes, usando o hook
beforeEach, por exemplo.
Caso algo dê errado durante a execução dos
testes, tais hooks correm o risco de não serem
executados, deixando "lixo" na aplicação.
16. Não use cy.wait(5000)
cy.wait('@myReq')
O Cypress já possui esperas automáticas com
diferentes timeout defaults para esperar por
elementos estarem visíveis, por animações
acabarem, por requisições serem enviadas e
respondidas e por páginas serem carregadas.
O que você pode fazer, para tornar seus testes
ainda mais robustos, é aguardor por elementos
estarem visíveis:
Ex.: cy.get('[data-cy="avatar"]').should('be.visible')
Ou então, você pode esperar por uma deteminada
requisição a qual você deu um alias.
Ex2.: cy.intercept(...).as('myReq')
...
17. start-server-and-test
Utilize mecanismos, tais como o uso da biblioteca
star-server-and-test, para inicializar o servidor da
aplicação antes da execução dos testes,
garantindo que a mesma será executada com o
código correto e que os testes serão executados
somente quando a aplicação estiver respondendo.
Além disso, tal abordagem ajudará na execução
dos testes em um servidor de integração contínua.
18. Defina a baseUrl
Além disso, tal URL pode ser sobrescrita por meio
de um arquivo cypress.env.json, variáveis de
ambiente (CYPRESS_ ou cypress_), linha de
comando, plugins, etc, possibilitando a execução
dos mesmos testes contra diferentes ambientes.
Ao definir a baseUrl no arquivo de configuração
(cypress.json), seus testes podem visitar as
páginas via URLs relativas.
19. Seguindo essas boas práticas, você
terá testes rápidos e robustos, nos
quais seu time confia e ajuda a
manter e evoluir.
22. Clonar o projeto
https://github.com/cypress-
io/cypress-realworld-app, acessá-
lo e rodar yarn install
Abrir o runner e filtrar pelo teste
transaction-view.spec.ts
Executar a suite e tirar uma
screenshot dos testes passando
E postar a screenshot no LinkedIn
com o texto "Eu vi a talk de
Cypress do Walmyr no
#MTCDendiCasa2021" (marcando
MTC, o Cypress.io e eu)
Tenho 10 cupons grátis pro meu curso
de Cypress intermediário, para os
primeiros que realizarem os seguintes
passos:
1.
2.
3.
4.
Desafio/Surpresa!