Vamos mergulhar no Cypress para testes de ponta a ponta

Publicados: 2022-03-10
Resumo rápido ↬ O teste de ponta a ponta é um tópico doloroso para você? Neste artigo, Ramona Schwering explica como lidar com testes de ponta a ponta com o Cypress e torná-lo não tão tedioso e caro para você, mas divertido.

O desenvolvimento de software sem testes automatizados é difícil de imaginar hoje. Uma boa variedade de diferentes procedimentos de teste garantirá um alto nível de qualidade. Como base para testes, podemos usar vários testes de unidade. Em cima disso, no meio da pirâmide, por assim dizer, estão os testes de integração. Os testes de ponta a ponta estão no topo, cobrindo os casos de uso mais críticos. Este terceiro tipo de teste será o foco deste artigo.

No entanto, o teste de ponta a ponta tem algumas armadilhas que são motivo de preocupação:

  • Os testes de ponta a ponta são lentos e, portanto, representam um obstáculo significativo em todas as estratégias de integração contínua e implantação contínua (CI/CD). Não apenas isso, mas imagine terminar uma tarefa, um recurso ou qualquer outra implementação – esperar a execução do teste pode esgotar a paciência de todos.
  • Esses testes de ponta a ponta são difíceis de manter, propensos a erros e caros em todos os sentidos devido ao esforço de depuração. Vários fatores podem causar isso. Seu teste deve parecer um assistente, nunca um obstáculo.
  • O maior pesadelo para os desenvolvedores é um teste esquisito, que é executado da mesma maneira, mas leva a resultados diferentes. É como um “Heisenbug”, que só ocorre se você não medir o aplicativo que está sendo testado — ou seja, se você não olhar para ele.
Heisenbugs
Heisenfails são reais e semelhantes aos Heisenbugs. (Visualização grande)

Mas não se preocupe: você não precisa sucumbir a essas armadilhas. Vejamos como evitar muitos deles . No entanto, não vou apenas prometer a lua e não cumprir. Neste guia, escreveremos alguns testes juntos, que divulguei para você em um repositório do GitHub. Dessa forma, espero mostrar a você que o teste de ponta a ponta pode ser divertido! Vamos começar.

O que são testes de ponta a ponta?

Ao falar sobre testes de ponta a ponta (ou E2E), gosto de me referir a eles como sendo “baseados em fluxo de trabalho”. A frase resume bem o teste de ponta a ponta: ele simula os fluxos de trabalho reais do usuário e deve incluir o maior número possível de áreas funcionais e partes da pilha de tecnologia usada no aplicativo. No final, o computador está fingindo ser um cliente e tenta se comportar como um usuário real. Esses testes são melhores para aplicar estresse constante em todo o sistema do seu aplicativo e, portanto, são uma ótima medida para garantir a qualidade quando toda a pilha de aplicativos está presente.

Robô
Testes de ponta a ponta são executados por um computador simulando um usuário real. (Visualização grande)

Vamos relembrar o que queremos alcançar com tudo isso. Sabemos que o teste de front-end é um conjunto de práticas para testar a interface do usuário de um aplicativo da Web, incluindo sua funcionalidade. Faz sentido — com essas medidas, podemos garantir que nosso aplicativo esteja funcionando corretamente e que nenhuma alteração futura quebre nosso código. Para conseguir isso de forma eficiente, você pode estar se perguntando o que e quanto você precisa testar.

Esta é uma pergunta válida. Você pode encontrar uma resposta possível em uma metáfora: a pirâmide de automação de teste, introduzida pela primeira vez por Mike Cohn e especificada por Martin Fowler, mostra como tornar os testes eficientes . Encontramos testes de unidade rápidos e baratos no nível mais baixo da pirâmide e testes de interface do usuário demorados e caros (testes de ponta a ponta) no topo.

Pirâmide de teste
A pirâmide de testes de automação. (Visualização grande)

Explicar isso e suas vantagens e desvantagens seria suficiente para seu próprio artigo. Eu gostaria de me concentrar em um nível. Testes de ponta a ponta, em particular, podem trazer melhorias significativas na qualidade se priorizados de forma eficiente. Ao fazer isso, podemos constantemente colocar nosso sistema sob estresse e garantir que as principais funções do nosso aplicativo funcionem corretamente.

Minha jornada para o cipreste

Quando comecei a aprender a escrever testes de ponta a ponta, usei Mink, uma biblioteca PHP, em cima do Behat, um framework de desenvolvimento orientado a comportamento (BDD) orientado a cenários. Comecei a usar o Selenium, com todas as suas vantagens e desvantagens. Como minha equipe começou a trabalhar muito com o Vue.js, mudamos para uma estrutura de teste baseada em JavaScript para garantir integração e compatibilidade perfeitas. Nossa escolha naquela época era Nightwatch.js, então construí nosso novo conjunto de testes do zero.

Durante esse tempo, muitas vezes nos deparamos com problemas de compatibilidade . Você poderia chamar isso de inferno de dependência - sem mencionar todas as limitações que vimos com o Selenium e mais tarde com o WebDriver.

  • Em nossa equipe, não conseguimos identificar a versão do Chrome do nosso CI. Portanto, se as atualizações do Chrome fossem lançadas, o Nightwatch.js não era rápido o suficiente para ser compatível, causando muitas falhas em nossos pipelines de teste.
  • O número de causas do lado do teste de testes esquisitos começou a aumentar, pois as possibilidades de espera do Nightwatch.js não correspondiam perfeitamente ao nosso produto.

Então, pensamos em construir nosso conjunto de testes novamente. Depois de visitar uma desconferência, descobri Cypress.

Cypress é uma estrutura de teste tudo-em-um que não usa Selenium ou WebDriver. A ferramenta usa Node.js para iniciar um navegador sob controle especial. Os testes nesta estrutura são executados no nível do navegador, não apenas no controle remoto. Isso oferece várias vantagens.

Em resumo, aqui estão as razões pelas quais eu escolhi este framework:

  • Excelente capacidade de depuração
    O executor de testes do Cypress pode voltar para qualquer estado do aplicativo por meio de instantâneos. Assim, podemos ver diretamente um erro e todas as etapas anteriores a ele. Além disso, há acesso total às ferramentas de desenvolvedor do Chrome (DevTools), e os cliques são totalmente registrados.
  • Melhores maneiras de aguardar ações no teste ou na interface do usuário ou nas respostas da API
    Cypress traz espera implícita, então não há necessidade de verificações apropriadas. Você também pode fazer o teste esperar por animações e respostas da API.
  • Os testes são escritos em JavaScript
    Isso reduz a curva de aprendizado para escrever testes. O executor de testes do Cypress é de código aberto, portanto, se encaixa em nossa estratégia de produto.

No entanto, este artigo é um guia, então vamos parar com essas informações gerais e seguir em frente.

Começando

Instale e inicie o Cypress

Vamos começar do zero. Em minhas palestras sobre o Cypress, geralmente começo criando um novo diretório via mkdir e instalando o Cypress imediatamente. A maneira mais fácil de instalar é mostrada neste desenho:

Cypress usa Node.js
Cypress usa Node.js (visualização grande)

Uma pequena dica: se você não quiser usar o npm, você pode instalar o Cypress via Yarn:

 yarn add cypress --dev

Uma alternativa é o download direto, usando as pastas ZIP que o Cypress disponibiliza. É isso! Quando a instalação estiver concluída, você estará pronto para começar.

Existem duas maneiras de começar a executar testes Cypress. A primeira é iniciar o Cypress no console e executar seus testes sem cabeça:

 ./node_modules/.bin/cypress run

A segunda maneira é usar um dos recursos elegantes do Cypress, que é seu executor de testes integrado. O executor de teste é uma interface do usuário para executar testes. Para iniciá-lo, você pode usar um comando semelhante:

 ./node_modules/.bin/cypress open

Este comando abrirá o executor de teste. Ao abrir o Cypress pela primeira vez, você verá esta interface:

Executor de testes do Cypress
Executor de testes da Cypress à primeira vista. (Visualização grande)

Cypress fornece alguns testes de amostra pré-escritos para mostrar seus recursos e fornecer alguns pontos de partida - esse é o motivo dos testes disponíveis. Vamos ignorá-los por enquanto, porque queremos escrever o nosso em breve. No entanto, lembre-se dessa área de “Testes de Integração”, pois ela será responsável por grande parte da mágica que acontecerá mais tarde.

Primeira impressão da estrutura do Cypress

Agora é hora de abrir nosso projeto recém-criado no ambiente de desenvolvimento integrado (IDE) de sua escolha. Se você navegar até esta pasta, verá a seguinte estrutura de teste:

 smashing-example └── cypress └── fixtures └── integration └── plugins └── support └── cypress.json

Vamos passar por essas pastas:

  • fixtures
    Aqui é onde você encontrará dados de teste fixos, que não têm relação com as outras entidades. Portanto, nenhum ID é armazenado aqui, o que pode mudar de acordo com o estado local.
  • integration
    Você encontrará os testes reais aqui.
  • plugins
    Aqui, você pode estender o Cypress, seja com plugins Cypress existentes ou seus próprios.
  • support
    Aqui, você pode estender o próprio Cypress. Seus próprios comandos e auxiliares estão localizados aqui.
  • cypress.json
    Modifique as configurações aqui, inclusive para o ambiente.

Tudo bem, acho que podemos encontrar o Cypress agora, seja o executor de testes ou o código-fonte. Mas como começamos? O que queremos testar?

Escolha um caso de teste

Um teste típico de ponta a ponta pode se tornar complexo, principalmente se tiver muitas etapas. Levaria muito tempo para executar manualmente. Devido a essa complexidade, os testes E2E podem ser difíceis de automatizar e lentos para executar. Como resultado, precisamos decidir cuidadosamente quais casos automatizar.

Na minha opinião, o termo “baseado em fluxo de trabalho” é fundamental : selecionamos casos de teste com base em histórias de usuários típicas. No entanto, devido aos tempos de execução, não é aconselhável cobrir todos os fluxos de trabalho disponíveis. Portanto, precisamos de uma maneira de priorizar nossos casos de teste.

Na minha equipe, tínhamos vários critérios para o nosso projeto. O caso de teste deve:

  • cobrir os fluxos de trabalho mais gerais e mais usados ​​de um recurso, como operações CRUD (o termo “caminho feliz” descreve muito bem esses fluxos de trabalho);
  • usar a análise de risco, cobrindo os fluxos de trabalho com testes E2E que são mais vulneráveis ​​(ou seja, onde os erros causariam mais danos);
  • evitar cobertura duplicada;
  • não necessariamente ser usado se os testes de unidade forem mais apropriados (use um teste E2E para testar a resposta do seu software a um erro, não o erro em si).

A segunda coisa mais importante a ter em mente é testar apenas o fluxo de trabalho que você deseja testar explicitamente. Todas as outras etapas necessárias para fazer seu teste funcionar devem ser feitas com operações de API fora do teste, para evitar testá-las. Dessa forma, você garantirá tempos mínimos de execução de teste e obterá um resultado claro do seu caso de teste se ele falhar. Pense neste fluxo de trabalho como um usuário final faria: Concentre-se no uso do recurso em vez da implementação técnica .

Exemplo:

Se você quiser testar o processo de checkout em uma loja online, não execute todas as outras etapas, como criar os produtos e categorias, mesmo que você precise deles para processar o checkout. Use, por exemplo, uma API ou um dump de banco de dados para fazer essas coisas e configure o teste apenas para o checkout.

Exemplo: Encontrando meus artigos na revista Smashing

Eu quero escrever um teste para este site, Smashing Magazine. Não posso garantir que este teste estará atualizado para sempre, mas vamos torcer para que dure. De qualquer forma, você poderá encontrar este exemplo em um repositório do GitHub.

Criando nosso primeiro teste de cipreste

Na pasta de integration , começaremos criando um novo arquivo. Vamos chamá-lo find-author.spec.js . O sufixo .spec significa “especificação”. Em termos de teste, isso se refere aos detalhes técnicos de um determinado recurso ou aplicativo que seu aplicativo deve atender.

Para transformar esse arquivo JavaScript vazio na casa de um teste, começaremos dando ao conjunto de testes sua estrutura. Usaremos o método chamado describe . describe() , ou context() , é usado para conter e organizar os testes. Em outras palavras, esse método serve como um quadro para nossos testes. Assim, nosso arquivo de teste ficará assim:

 // find-author.spec.js describe('Find authors at smashing', () => { //... });

O próximo passo é criar o teste real. Usaremos o método it . it() , ou specify() , é usado para representar o teste real. Como você pode ver, podemos capturar vários testes em um arquivo, o que permite algumas excelentes opções de estruturação.

 // find-author.spec.js describe('Find authors at smashing', () => { it('Find the author Ramona Schwering', () => { cy.log('This is our brand-new test'); }); });

Pequena dica : Se você conhece o Mocha, deve ter notado algumas semelhanças. Cypress é construído em cima do Mocha, então a sintaxe é a mesma.

Tudo bem, vamos prosseguir. Se executarmos nosso teste no executor de testes do Cypress, perceberemos que o Cypress abrirá um navegador para executar o teste. Este navegador é visto na captura de tela abaixo:

Execução do nosso primeiro teste
Nosso primeiro teste, executado no executor de testes do Cypress. (Visualização grande)

Parabéns! Escrevemos nosso primeiro teste! Claro, não adianta muito. Precisamos continuar. Vamos preencher nosso teste com vida.

Preencha o teste com vida

Qual é a primeira coisa a fazer ao testar um site? Certo, precisamos abrir o site. Podemos fazer isso usando um comando Cypress. Qual é o comando, você deve estar se perguntando?

Trabalhando com comandos

Existem basicamente dois tipos de instruções usadas em um teste E2E. O primeiro tipo de instrução, os comandos, representa as etapas individuais do teste. No contexto do Cypress, comandos são tudo o que o Cypress faz para interagir com seu site. Essa interação pode ser qualquer coisa – um clique, rolar o site ou até encontrar um elemento. Como resultado, os comandos serão uma das coisas importantes com as quais preencheremos nosso teste.

Então, nosso primeiro comando será o de navegar até o site — smashingmagazine.com . Este comando é chamado de visit .

Usando-o, nosso teste ficará assim:

 // find-author.spec.js describe('Find authors at smashing', () => { it('Find the author Ramona Schwering', () => { cy.visit('https://www.smashingmagazine.com/'); }); });

Há um comando que eu uso com frequência – e você também. Chama- get :

 cy.get('selector');

Este comando retorna um elemento de acordo com seu seletor — semelhante ao $(…) do jQuery. Então, você usaria este comando para encontrar as partes com as quais interagir. Normalmente, você o usaria para iniciar uma cadeia de comandos. Mas espere - o que significa uma cadeia de comandos?

Conforme mencionado no início deste artigo, todos os testes e tudo o mais que os acompanha são escritos em JavaScript. Você pode colocar os comandos nos testes (ou seja, as instruções) em uma cadeia (encadeada, em outras palavras). Isso significa que os comandos podem passar um assunto (ou valor de retorno) de um comando para o comando a seguir, como sabemos de muitas estruturas de teste.

Tudo bem, vamos iniciar uma cadeia de comandos com o comando get . Para encontrar um elemento com get , precisamos primeiro encontrar seu seletor. Encontrar um seletor exclusivo é essencial, porque o Cypress retornaria todos os elementos correspondentes; então, tenha isso em mente e evite-o se não for intencional.

Interagindo com elementos

O próprio Cypress possui um recurso para ajudá-lo a encontrar os seletores dos elementos com os quais deseja trabalhar. Esse recurso é chamado de Selector Playground e ajuda você a descobrir seletores exclusivos de um componente ou a ver todos os elementos correspondentes para um seletor ou uma string de texto. Então, esse recurso pode te ajudar muito nessa tarefa. Para ativá-lo, basta clicar no ícone de mira no cabeçalho da interface do usuário do seu teste e passar o mouse sobre o elemento desejado:

Usando o playground seletor
Usando o Selector Playground para identificar seletores exclusivos. (Visualização grande)

Como visto na captura de tela acima, uma dica de ferramenta exibirá o seletor ao passar o mouse ou nesta pequena barra sob o ícone de mira, que apareceu quando o elemento foi clicado. Nesta barra, você também pode ver quantos elementos corresponderiam ao seletor fornecido - garantindo sua exclusividade no nosso caso.

Às vezes, esses seletores gerados automaticamente podem não ser os que você deseja usar (por exemplo, se são longos ou difíceis de ler ou não atendem aos seus outros critérios). O seletor gerado abaixo é difícil de entender e muito longo, na minha humilde opinião:

Não é um seletor ideal
Este seletor pode não ser ideal para usar. (Visualização grande)

Nesse caso, eu voltaria ao DevTools do navegador para encontrar meus seletores exclusivos. Você pode estar familiarizado com essas ferramentas; no meu caso, geralmente escolho o Chrome para essa finalidade. No entanto, outros navegadores compatíveis podem fornecer recursos semelhantes. O processo é semelhante ao Selector Playground, exceto que estamos usando os recursos do DevTools na guia "Element".

Encontrar seletores por meio de ferramentas de desenvolvedor
Usando as ferramentas de desenvolvedor do navegador para encontrar seletores exclusivos. (Visualização grande)

Para garantir que um seletor seja exclusivo, recomendo pesquisá-lo na visualização de código do DevTools. Se você encontrar apenas um resultado, pode ter certeza de que é único.

Você sabia que existem muitos tipos de seletores diferentes ? Dependendo da variedade, os testes podem parecer e até se comportar de maneira bem diferente. Algumas variedades são mais adequadas para testes de ponta a ponta do que outras. Se você quiser saber quais seletores usar para manter seus testes estáveis ​​e limpos, posso indicar um de meus artigos que aborda esse problema. Os próprios desenvolvedores do Cypress fornecem algumas orientações sobre esse tópico em suas melhores práticas.

Nosso teste como uma sequência de comandos

OK, de volta ao nosso teste. Nele, queremos exibir nosso fluxo de trabalho:

“Eu, como usuário, pesquisarei o artigo do autor e navegarei até o site do autor pela área de referência em um de seus artigos.”

Reproduziremos as etapas que um usuário executaria usando comandos. Vou colar abaixo o teste finalizado com comentários, que explicarão os passos:

 // find-author.spec.js it('Find the author Ramona Schwering', () => { // Open the website cy.visit('https://www.smashingmagazine.com'); // Enter author's name in search field cy.get('#js-search-input').type('Ramona Schwering'); // Navigate to author's article cy.get('h2 > a').first().click(); // Open the author's page cy.get('.author-post__author-title').click(); });

Este exemplo trata do fluxo de trabalho que queremos testar. Cypress irá executar este teste. Então, é hora de dizer “Parabéns”? Finalmente terminamos de escrever nosso primeiro teste?

Bem, por favor, dê uma olhada mais de perto . Cypress irá executá-lo, mas só fará o que o teste diz, que é o que você escreveu. Se você executá-lo no executor de testes, poderá ver se ele passou - mas não no caso de você executá-lo sem cabeça. Com este teste, só sabemos se o Cypress conseguiu executar nossos comandos com sucesso - não se acabamos no site do autor. Então, precisamos ensinar nosso teste para determinar isso.

Trabalhando com afirmações

O segundo tipo de instrução cuida das descrições do estado desejado da interface do usuário — ou seja, se algo deve existir, estar visível ou não estar mais visível. As afirmações em Cypress são baseadas em afirmações Chai e Sinon-Chai, o que é perceptível na sintaxe.

Lembre-se de que queremos verificar se estamos na página de perfil do autor — a minha neste exemplo. Então, precisamos adicionar uma afirmação para exatamente isso:

 // find-author.spec.js it('Find the author Ramona Schwering', () => { // Open the website cy.visit('https://www.smashingmagazine.com'); // Enter author's name in search field cy.get('#js-search-input').type('Ramona Schwering'); // Navigate to author's article cy.get('h2 > a').first().click(); // Open the author's page cy.get('.author-post__author-title').click(); // Check if we're on the author's site cy.contains('.author__title', 'Ramona Schwering').should('be.visible'); });

Muito bem, agora escrevemos um teste que tem valor. Então, sim, parabéns por escrever seu primeiro teste... mesmo que ainda não esteja perfeito.

Vamos fazer nosso teste bonito

Mesmo se tivéssemos conseguido escrever um primeiro teste significativo e aprendido o conceito central no processo, eu não faria o merge deste ainda se fosse proposto em um pull request. Algumas coisas são deixadas a fazer para fazê-lo brilhar.

Sem pressa

Cypress tem uma opção de repetição embutida em quase todos os comandos, então você não precisa esperar para ver se, por exemplo, um elemento já existe. No entanto, isso apenas verifica se existe um elemento no DOM, não mais do que isso. O Cypress não pode prever tudo o que seu aplicativo faz, portanto, pode haver alguma falha se você confiar apenas nisso.

Tempo em testes de ponta a ponta
O tempo é um aspecto importante nos testes de ponta a ponta. (Visualização grande)

O que um usuário faria se quisesse ver um site que ainda está carregando? Eles provavelmente esperariam até que algumas partes do site se tornassem visíveis (portanto, carregadas) e então interagiriam com elas. Em nosso teste, queremos imitar exatamente isso: queremos aguardar as alterações na interface do usuário antes de começar a interagir . Na maioria dos casos, limitamos esse comportamento aos elementos de que precisamos, usando asserções nesses elementos.

Como você pode ver, devemos fazer nosso teste esperar em várias ocasiões. No entanto, esperar muitas vezes também não é bom. Como regra geral, sugiro usar uma asserção para verificar se o elemento com o qual interagir foi totalmente carregado, como a primeira etapa para determinar se o site que está sendo testado foi carregado.

Vamos dar uma olhada em tal parte do nosso teste como um exemplo. Eu adicionei uma declaração para garantir que nossa página tenha sido totalmente carregada :

 // find-author-assertions.spec.js // Open website cy.visit('https://www.smashingmagazine.com'); // Ensure site is fully loaded cy.get('.headline-content').should('be.visible'); // Enter author's name in the search field cy.get('#js-search-input').type('Ramona Schwering');

Continue adicionando asserções dessa maneira a todas as instâncias em que nosso site terá tempos de carregamento ou vários elementos que precisam ser renderizados novamente. Para obter o arquivo de teste completo, consulte o teste correspondente no repositório do GitHub.

Para evitar cair na armadilha de testes esquisitos, gostaria de dar uma última dica: Nunca use tempos de espera fixos, como cy.wait(500) ou algo parecido.

As respostas da API são seus amigos

Há uma possibilidade de espera em particular que adoro usar em meus testes. No Cypress, é possível trabalhar com recursos de rede — outra maneira útil de aguardar em seu aplicativo é usar esses recursos para trabalhar com solicitações de rede . Dessa forma, você pode fazer o teste aguardar uma resposta de API bem-sucedida.

Se lembrarmos do nosso fluxo de trabalho como exemplo, uma etapa poderia fazer um ótimo uso de uma possibilidade de espera de API. Estou pensando em pesquisar. Uma história de usuário correspondente pode ser a seguinte:

“Eu, como desenvolvedor, quero ter certeza de que nossos resultados de pesquisa foram totalmente carregados para que nenhum artigo de resultados mais antigos engane nosso teste.”

Vamos aplicar isso ao nosso teste. Antes de tudo, precisamos definir a rota que queremos esperar mais tarde. Podemos usar o comando intercept para isso. Eu pesquisaria a solicitação, trazendo os dados de que preciso — os resultados da pesquisa neste caso.

Para manter este exemplo simples, usarei um curinga para a URL. Depois disso, usarei um alias para que o Cypress possa trabalhar com essa rota posteriormente.

 // find-author-hooks.spec.js // Set the route to work with it('Find the author Ramona Schwering', () => { // Route to wait for later cy.intercept({ url: '*/indexes/smashingmagazine/*', method: 'POST' }).as('search'); // With this alias Cypress will find the request again //...

No Cypress, todas as rotas definidas são exibidas no início do teste. Então, eu gostaria de colocar esses comandos de intercept no início do meu teste também.

Rota da API no executor de testes do Cypress
A rota da API será exibida na parte superior do nosso teste. (Visualização grande)

Agora, podemos usar esse alias de rota em asserções. A maneira mais enxuta de fazer isso seria com o comando wait do Cypress, diretamente com o alias mencionado anteriormente. No entanto, usar esse comando sozinho levaria à espera pela resposta, independentemente de seu resultado . Mesmo códigos de erro como 400 ou 500 contariam como aprovados, enquanto seu aplicativo provavelmente seria interrompido. Então, eu recomendaria adicionar outra afirmação como esta:

 // find-author-hooks.spec.js // Later: Assertion of the search request's status code cy.wait('@search') .its('response.statusCode').should('equal', 200);
Asserção na resposta da API
Asserção sobre a resposta da API, como visto no executor de testes do Cypress. (Visualização grande)

Dessa forma, podemos aguardar os dados do software, alterações, etc. com precisão, sem perder tempo ou ter problemas se o aplicativo estiver muito sobrecarregado. Novamente, você pode encontrar o arquivo de exemplo completo no meu repositório GitHub.

Configurando o Cypress

Deixei de fora um pequeno detalhe. Se você der uma olhada no exemplo de teste completo, ele difere um pouco daqueles que usamos aqui neste guia.

 // Cypress describe('Find author at smashing', () => { beforeEach(() => { // Open website cy.visit('https://www.smashingmagazine.com'); }); //...

Eu só uso uma barra para abrir o site da Smashing Magazine. Como isso funciona? Bem, usar este comando dessa forma navegará para o baseUrl de nossos testes. baseUrl é um valor de configuração que pode ser usado como prefixo para a URL do comando cy.visit() ou cy.request() . Entre outros valores, podemos definir esse valor no arquivo cypress.json . Para nosso teste, definiremos o baseUrl assim:

 // cypress.json { "baseUrl": "https://www.smashingmagazine.com" }

Menção Honrosa: Ganchos

Há um tópico restante que quero mencionar, mesmo que nosso teste de exemplo não seja adequado para usá-lo. Como é comum em outros frameworks de teste, podemos definir o que acontece antes e depois de nossos testes por meio dos chamados ganchos de ciclo de vida. Mais precisamente, existem para executar código antes ou depois de um ou de todos os testes:

 // Cypress describe('Hooks', function() { before(() => { // Runs once before all tests }); after(() => { // Runs once after all tests }); beforeEach(() => { // Runs before each test }); afterEach(() => { // Runs after each test }); });

Queremos preencher nosso arquivo de teste com mais de um teste, portanto, devemos procurar etapas comuns que desejamos executar antes ou depois delas. Nossa primeira linha é um exemplo disso, sendo o comando visit . Supondo que queremos abrir este site antes de cada um desses testes, um gancho beforeEach em nosso exemplo ficaria assim:

 // Cypress describe('Find author at smashing', () => { beforeEach(() => { // Open website cy.visit('https://www.smashingmagazine.com'); }); //... 
antes de cada gancho
O gancho beforeEach é exibido no log do executor de teste. (Visualização grande)

Costumo usar isso no meu trabalho diário para garantir, por exemplo, que meu aplicativo seja redefinido para seu estado padrão antes do teste , isolando assim o teste de outros testes. ( Nunca confie em testes anteriores! ) Execute seus testes isolados uns dos outros para manter o controle sobre o estado do aplicativo.

Cada teste deve ser executado por conta própria — independentemente de outros testes. Isso é fundamental para garantir resultados de teste válidos . Para obter detalhes sobre isso, consulte a seção “Dados que costumávamos compartilhar” em um dos meus artigos recentes. Por enquanto, consulte o exemplo completo no GitHub se quiser ver o teste inteiro.

Conclusão

Na minha opinião, os testes de ponta a ponta são um componente essencial da CI, mantendo a qualidade das aplicações em alto nível e ao mesmo tempo aliviando o trabalho dos testadores. Cypress é minha ferramenta de escolha para depurar testes de ponta a ponta de forma rápida, estável e eficiente, e para executá-los paralelamente a qualquer solicitação de pull como parte do CI. A curva de aprendizado é suave se você já estiver familiarizado com JavaScript.

Espero ter sido capaz de guiá-lo um pouco e ter dado a você um ponto de partida para escrever testes Cypress e algumas dicas práticas para começar. Claro, todos os exemplos de código estão disponíveis no repositório GitHub, então fique à vontade para dar uma olhada.

Claro, este é apenas um ponto de partida; há muito mais coisas para aprender e discutir sobre os testes Cypress - vou deixar algumas sugestões sobre o que aprender a seguir. Com isso em mente, bons testes!

Recursos

  • Exemplo de esmagamento original, Ramona Schwering
    Repositório do GitHub para o exemplo neste artigo.
  • Documentação do cipreste
  • “Receitas”, Cipreste
    Uma seleção de exemplos, receitas e cursos.
  • “Aprenda a codificar com JavaScript: Cypress” (lição), CodeLikeThis
  • Melhores práticas para escrever testes de ponta a ponta”, Shopware Docs