Aprenda como tornar seus testes automatizados mais rápidos autenticando via API
Testes automatizados de interface gráfica de usuário devem ser independentes uns dos outros. Além disso, tais testes devem depender o mínimo possível da interface gráfica de usuário para chegar ao estado desajado para que o teste propriamente dito ocorra.
Parece contraintuitivo, mas é isso mesmo.
Pela interface gráfica de usuário, devemos testar só uma vez. Mais do que isso é desperdício.
No entanto, na maioria das aplicações web, para testarmos certas funcionalidades, o(a) usuário(a) deve estar autenticado(a) no sistema. Porém, como autenticar tal usuário(a) sem passar pela página de login?
É exatamente isso que vou te mostrar nessa pitada de Cypress.
Obs.: Vale lembrar que esta é só uma alternativa, e que talvez não seja adequada para o seu caso de uso. Para mais exemplos, recomendo ler a seção de estratégias de teste (testing strategies) da documentação oficial do Cypress.
Para facilitar a explicação, vou utilizar como exemplo um projeto real para o qual tenho contribuído recentemente. O BR Modelo Web.
Imaginemos o seguinte caso de teste.
// cypress/e2e/programmaticLogin.cy.js
it('successfully logs in programmatically', () => {
cy.intercept('GET', `${Cypress.env('apiUrl')}/models?userId=*`)
.as('getUserModels')
cy.request('POST', `${Cypress.env('apiUrl')}/users/login`, {
username: Cypress.env('userEmail'),
password: Cypress.env('userPassword'),
}).then((response) => {
cy.setCookie('sessionId', response.body.sessionId)
cy.setCookie('userId', response.body.userId)
cy.setCookie('userName', response.body.userName)
})
cy.visit('/#!/main')
cy.wait('@getUserModels')
cy.contains('h2', 'Models').should('be.visible')
}
Deixei destacada a parte do código que realiza a autenticação de forma programática.
De qualquer forma, vamos entender o que todo o teste faz.
Primeiro, dentro do corpo do teste, ou seja, dentro do bloco it, uso o comando cy.intercept. Com tal comando, posso “escutar” 👂 chamadas de rede, tal como uma requisição do tipo GET para a URL da API da aplicação que busca as modelagens do usuário logado. Depois, dou um alias (algo como um apelido) à tal intercept. O alias é getUserModels.
Daí, vem a parte em que começa a autenticação de forma programática.
Nessa parte, uso a funcionalidade cy.request para fazer uma requisição do tipo POST para a URL de login, passando no body da requisição as propriedades username e password, ambas vindas de variáveis (usando a funcionalidade Cypress.env()). Faço isso para não expor dados sensíveis.
Depois, encadeio ao comando cy.request() um .then(), o qual recebe como argumento uma arrow function, a qual recebe como argumento a resposta da requisição do cy.request().
No corpo dessa arrow function, utilizo a funcionalidade cy.setCookie() para, como o nome propõe, definir alguns cookies com base no corpo (body) da resposta da requisição. Estes são exatamente os cookies que são definidos quando o(a) usuário(a) realiza o login via interface gráfica de usuário.
Com os cookies definidos, visito a página inicial da aplicação.
Por fim, faço algumas verificações.
Primeiro, aguardo pela requisição do intercept criado anteriormente ocorrer, com o cy.wait(), passando ao mesmo o alias criado anteriormente (‘@getUserModels’).
E então, verifico que certo elemento está visível (um h2 com o texto Models), o qual somente é visível para usuários autenticados, provando que o login ocorreu com sucesso.
Pronto! 🎉
Atenção: Quando testando a funcionalidade de login, é recomendado que tal teste ocorra via interface gráfica de usuário. No entanto, para todas as outras funcionalidades que requerem o(a) usuário(a) autenticado(a), utilize o login de forma programática e salve alguns segundos em cada teste!
Bônus – comando customizado
Visto que mais de uma suíte de testes necessitará fazer o login de forma programática, podemos mover tal lógica para um comando customizado, o qual pode ser reaproveitado quantas vezes forem necessárias.
Veja como ficaria o código do teste
// cypress/e2e/programmaticLogin.cy.js
it('successfully logs in via GUI', () => {
cy.intercept('GET', `${Cypress.env('apiUrl')}/models?userId=*`)
.as('getUserModels')
cy.loginViaAPI()
cy.wait('@getUserModels')
cy.contains('h2', 'Models').should('be.visible')
})
E o comando customizado.
// cypress/support/commands.js
Cypress.Commands.add('loginViaAPI', (
email = Cypress.env('userEmail'),
password = Cypress.env('userPassword')
) => {
cy.request('POST', `${Cypress.env('apiUrl')}/users/login`, {
username: email,
password,
}).then((response) => {
cy.setCookie('sessionId', response.body.sessionId)
cy.setCookie('userId', response.body.userId)
cy.setCookie('userName', response.body.userName)
cy.visit('/#!/main')
})
})
No teste, agora toda a lógica de cy.request e cy.setCookie fica abstrata. Somente chamo o comando cy.loginViaAPI() e ele se vira para fazer o que precisa para autenticar o(a) usuário(a).
Já o comando customizado, além de possuir a lógica anterior, agora também pode receber um email e uma senha como argumentos. Porém, caso nenhum argumento seja passado, tais valores já têm padrões vindos de variáveis.
Além disso, resolvi mover a visita à página inicial para o comando customizado.
Veja o teste rodando e autenticando sem precisar passar pela página de login. Parece mágica! 🪄

É isso aí!
Espero que tenha gostado.
Acesse a versão final nesse repositório público em meu perfil no GitHub.
Ou então, o repositório do projeto BR Modelo Web App.
Aproveita pra deixar uma star! ⭐
Gostou do conteúdo? Deixa um comentário.
Ficou curioso(a) e quer aprender mais sobre automação de testes com Cypress? Conheça os cursos da Escola TAT.
- Cypress Playground
- Cypress, do Zero à Nuvem
- Cypress Simulator
- Testes End-to-End com Cypress e Cucumber: Guia Definitivo
- Cypress intermediário
- Cypress avançado
- Boas práticas em automação de testes com Cypress
- Testes end-to-end com Cypress
👋 Até a próxima e bons testes!
Este conteúdo foi traduzido para o inglês e pode ser encontrado no DEV Community.
Parabéns, um passo a passo que me facilitaria muito a algum tempo atrás.
Obrigado por deixar o caminho das pedras um pouco mais facil!
É um prazer compartilhar um pouco de conhecimento com a comunidade Eduardo.
Excelente conteúdo, Walmyr! Saberia dizer se todas as páginas de login suportam tal login via request, mesmo que precise de adaptações? Pergunto porque na aplicação da empresa que trabalho, é utilizado as tecnologias Kong e Keycloak, que acabam interferindo bastante no login e aparecem algumas chaves de autenticação que são passadas para as próximas requisições que não consegui saber da onde vieram inicialmente.
Obrigado Rafael.
Respondendo sua pergunta, creio que não sejam todas as páginas que dispõe de tal facilidade.
No entanto, é sempre bom quando se pensa em testabilidade durante o desenvolvimento da aplicação.
Sobre as tecnologias Long e Keycloak, nunca usei, portanto, não saberia te ajudar com isso.