Integrando testes Cypress com Docker, Buildkite e CICD #frontend@twiliosendgrid

Publicados: 2020-12-30

Escrevemos muitos testes Cypress de ponta a ponta (E2E) para validar que nossos aplicativos da Web ainda estão funcionando conforme o esperado com o back-end. Depois de escrever esses testes de automação do navegador, gostaríamos de sempre ter esses testes Cypress executados ou acionados de alguma forma, como nossos testes de unidade, antes de mesclar código e implantar em determinados ambientes. Isso nos levou a querer executar nossos testes Cypress em um contêiner do Docker para integrar com nosso provedor de integração contínua (CI) e as máquinas que usamos na nuvem para executar esses contêineres.

Quando se trata de fluxos de implantação, usamos o Buildkite como nosso provedor de CI. Isso nos permite gerar uma compilação de etapas automatizadas para nosso aplicativo em um pipeline do Buildkite quando planejamos mover o código em toda a linha. Para mais contexto, um pipeline é um local geralmente vinculado ao repositório de um aplicativo onde podemos ver compilações ou acionar compilações com determinadas etapas a serem executadas quando você cria solicitações pull, envia novas alterações de código, mescla código para mestre e implanta em diferentes ambientes . Criamos vários pipelines para fins separados, como implantação, testes Cypress acionados e testes específicos do Cypress executados em um cronograma.

Esta postagem de blog pressupõe que você já escreveu testes Cypress antes e tem alguns testes em execução, mas gostaria de ter ideias sobre como executar esses testes o tempo todo em seus fluxos de desenvolvimento e implantação. Se você quiser mais uma visão geral sobre como escrever testes Cypress, você pode conferir esta postagem anterior no blog e revisitar isso quando tiver algo para executar.

Nosso objetivo é orientá-lo através de ideias sobre como você pode integrar testes Cypress em um contêiner do Docker com seu provedor de CI, analisando como fizemos isso com o Docker Compose e o Buildkite em nosso pipeline de implantação. Essas ideias podem ser expandidas em sua infraestrutura para as estratégias, comandos e variáveis ​​de ambiente a serem aplicadas ao acionar testes Cypress.

Nosso fluxo CICD padrão

Em nosso fluxo padrão de desenvolvimento e implantação, configuramos dois pipelines:

  1. O primeiro lida com nossas etapas de implantação para quando enviamos código.
  2. O segundo aciona nossos testes Cypress para serem executados em paralelo e serem gravados. O sucesso ou falha disso afeta o pipeline de implantação.

Em nosso pipeline de implantação, criamos nossos ativos de aplicativos da Web, executamos testes de unidade e temos etapas para acionar testes Cypress selecionados antes de implantar em cada ambiente. Garantimos que eles passem antes de liberar a capacidade de implantar um botão de pressão. Esses testes Cypress acionados no segundo pipeline também são executados em um contêiner do Docker e são conectados ao Cypress Dashboard pago por meio de uma chave de gravação para que possamos analisar os vídeos, capturas de tela e saída do console desses testes Cypress para depurar quaisquer problemas.

Usando as entradas selecionadas do Buildkite , criamos uma dinâmica, escolha sua própria aventura para que os usuários possam selecionar “Sim” ou “Não” para decidir quais pastas de especificações do Cypress executar e verificar à medida que enviamos mais código. A resposta padrão seria “Não” para todas as opções, mas o valor de “Sim” seria o caminho glob para a pasta de especificações do Cypress.

Às vezes, não queremos executar todos os testes do Cypress se nossa alteração de código não afetar outras páginas. Nós, em vez disso, queremos apenas acionar os testes que sabemos que serão afetados. Também podemos precisar implantar uma correção rápida na produção para um problema de bug urgente, pois nos sentimos confiantes o suficiente para não executar nossos testes Cypress, que podem levar de 0 a 10 minutos, dependendo de quantos testes acionarmos. Fornecemos um exemplo visualmente e nas etapas de YML para esta parte.

Em seguida, implementamos nosso próprio script Bash chamado runCypress.sh para ser executado após essa etapa de seleção para analisar os valores "Sim" ou "Não" selecionados. Fazemos isso para formar uma lista de caminhos de especificação separados por vírgula para executar e anexar como uma opção, --spec , ao nosso eventual comando Cypress que é executado em um contêiner do Docker em um pipeline acionado. Exportamos variáveis ​​de ambiente, como a lista formada de especificações em “CYPRESS_SPECS” e o ambiente de teste atual em “CYPRESS_TEST_ENV” para serem usadas no pipeline que estamos acionando no final do script com buildkite-agent pipeline upload "$DIRNAME"/triggerCypress.yml .

Você deve ter notado como também exportamos uma variável de ambiente “ASYNC”. No Buildkite, você pode optar por ter uma etapa de compilação acionada bloqueando ou não bloqueando em termos de sucesso ou falha. Se tivermos "ASYNC" definido como verdadeiro, nossas principais etapas do pipeline de implantação continuarão em execução e não aguardarão a conclusão dos testes Cypress acionados em um pipeline diferente. O sucesso ou falha do pipeline não afeta o sucesso ou falha do pipeline de implantação.

Se tivermos "ASYNC" definido como false, nossas principais etapas do pipeline de implantação serão bloqueadas até que os testes Cypress acionados em um pipeline diferente sejam concluídos. O sucesso ou falha da compilação acionada leva ao sucesso ou falha geral do pipeline de implantação, onde ele é retomado depois.

Quando nosso código ainda está em uma ramificação de recurso com uma solicitação de pull aberta, gostamos de enviar mais alterações, acionar alguns testes do Cypress e ver como as coisas se comportam. Mas nem sempre queremos bloquear a execução do restante das etapas do pipeline de implantação se os testes acionados falharem, pois há potencialmente mais alterações ao longo do caminho. Nesse cenário, definimos “ASYNC” como false para não bloquear se os testes do Cypress falharem. Para o caso em que já mesclamos nossa solicitação pull no master e implantamos no staging, mas queremos acionar os testes Cypress antes de implantar na produção, definimos “ASYNC” como true, pois queremos que os testes Cypress sempre passem antes de sair para produção .

Voltando a runCypress.sh , lembramos que o script aciona a execução do segundo pipeline chamando o arquivo triggerCypress.yml com valores de variáveis ​​de ambiente atribuídos. O arquivo triggerCypress.yml se parece com isso. Você notará que a etapa “trigger” e a interpolação de valores nas mensagens de compilação são úteis para depuração e nomes de etapas dinâmicas.

Quer acionemos os testes Cypress para serem executados de nosso pipeline de implantação para um pipeline de gatilho separado ou executemos os testes Cypress em um agendamento em um pipeline dedicado, seguimos e reutilizamos as mesmas etapas enquanto alteramos apenas os valores das variáveis ​​de ambiente.

Essas etapas envolvem:

  1. Criando a imagem do Docker com uma tag mais recente e uma tag de versão exclusiva
  2. Empurrando a imagem do Docker para nosso registro privado
  3. Puxando a mesma imagem para executar nossos testes Cypress com base em nossos valores de variável de ambiente em um contêiner do Docker

Essas etapas são descritas em um arquivo pipeline.cypress.yml da seguinte forma:

Quando acionamos os testes do Cypress para serem executados, ele inicia uma compilação separada no pipeline de gatilho do Cypress. Com base no sucesso ou falha da compilação, a execução de teste do Cypress bloqueará ou nos permitirá implantar na produção quando passarmos da preparação para a produção para compilações de ramificação mestre.

Clicar na etapa “Triggered cypress/integration/…” levará você para a construção do pipeline acionado com uma visualização como esta para ver como foram os testes.

Se você está curioso sobre como a parte do Docker está toda conectada, nosso Dockerfile.cypress e docker-compose.cypress.yml usam essas variáveis ​​de ambiente exportadas de nossos pipelines para usar o comando Cypress apropriado do package.json do nosso aplicativo apontando para a direita ambiente de teste e executando os arquivos de especificação selecionados. Os snippets abaixo mostram nossa abordagem geral que você pode expandir e melhorar para ser mais flexível.


Fora dos testes executados durante nossos ciclos usuais de integração e implantação, criamos pipelines Buildkite dedicados. Esses pipelines são executados em um cronograma para testes importantes em nosso ambiente de teste para garantir que nossos serviços de front-end e back-end estejam funcionando corretamente. Reutilizamos etapas de pipeline semelhantes, ajustamos determinados valores de variáveis ​​de ambiente nas configurações do pipeline do Buildkite e configuramos um agendamento cron para ser executado em um horário agendado. Isso nos ajuda a detectar muitos bugs e problemas com o ambiente de teste à medida que continuamos a monitorar o desempenho de nossos testes e se algo downstream ou de nossos próprios pushes de código pode ter levado a testes com falha.

Paralelização

Também utilizamos o sinalizador de paralelização para aproveitar o número de máquinas da AWS que podemos ativar em nossa fila de agentes de compilação configurados por nossa equipe de operações. Com este sinalizador de paralelização, o Cypress automaticamente traz um certo número de máquinas com base no número que definimos na propriedade “paralelismo” do Buildkite.

Conseguimos executar mais de 200 testes em cerca de 5 minutos para um de nossos repositórios de aplicativos.

Em seguida, ele espalha todos os testes do Cypress para serem executados em paralelo nessas máquinas, mantendo a gravação de cada um dos testes para uma execução de compilação específica. Isso aumentou drasticamente nossos tempos de execução de teste!

Aqui estão algumas dicas ao paralelizar seus testes Cypress:

  • Siga as sugestões no Dashboard Service para o número ideal de máquinas e tenha o número de máquinas definido em uma variável de ambiente para flexibilidade em seus pipelines.
  • Dividido em arquivos de teste menores, especialmente dividindo testes de execução mais longa em partes, podemos paralelizar melhor entre as máquinas.
  • Certifique-se de que seus testes Cypress sejam isolados e não afetem uns aos outros ou dependam uns dos outros. Ao lidar com fluxos relacionados a atualização, criação ou exclusão, use usuários e recursos de dados separados para evitar que os testes se atropelem e entrem em condições de corrida. Seus arquivos de teste podem ser executados em qualquer ordem, portanto, certifique-se de que isso não seja um problema ao executar todos os seus testes.
  • Para o Buildkite, lembre-se de passar o valor da variável de ambiente Buildkite ID de compilação para a --ci-build-id , além da opção parallel , para que ele saiba qual execução de compilação exclusiva associar ao paralelizar testes entre máquinas.

Rever:

Para conectar seus testes Cypress ao seu provedor de CI, como o Buildkite, você precisará:

  1. Crie uma imagem do Docker com o código do aplicativo, usando a imagem base Cypress necessária e as dependências necessárias para executar os testes em um ambiente Node em determinados navegadores.
  2. Envie sua imagem do Docker para um registro com determinadas tags
  3. Puxe a mesma imagem para baixo em uma etapa posterior
  4. Execute seus testes Cypress no modo headless e com chaves de gravação se estiver usando o Cypress Dashboard Service.
  5. Defina diferentes valores de variáveis ​​de ambiente e conecte-os aos comandos que você executa para o Cypress acionar testes Cypress selecionados em um determinado ambiente de teste nesses contêineres do Docker.

Essas etapas gerais podem ser reutilizadas e aplicadas a testes Cypress executados em uma programação e outros casos de uso, como acionar testes para execução em navegadores selecionados, além de seus pipelines de implantação. A chave é aproveitar os recursos do seu provedor de CI e configurar seus comandos para serem flexíveis e configuráveis ​​com base nos valores das variáveis ​​de ambiente.

Configure seus comandos para serem flexíveis e configuráveis ​​com base nos valores das variáveis ​​de ambiente.

Depois de executar seus testes no Docker com seu provedor de CI (e se você pagar pelo Dashboard Service), poderá aproveitar a paralelização de seus testes em várias máquinas. Você pode ter que modificar os testes e recursos existentes para que eles não sejam dependentes de outros para evitar que testes atropelem uns aos outros.

Também discutimos ideias que você pode experimentar por conta própria, como criar um conjunto de testes para validar sua API de back-end ou acionar testes para serem executados em um navegador de sua escolha. Há também mais maneiras de configurar a integração contínua aqui nos documentos do Cypress .

Além disso, é importante executar esses testes Cypress durante os fluxos de implantação ou intervalos programados para garantir que seus ambientes de desenvolvimento estejam funcionando conforme o esperado o tempo todo. Houve inúmeras vezes em que nossos testes Cypress detectaram problemas relacionados a serviços de back-end downstream que estavam inativos ou alterados de alguma forma, manifestando-se em erros de aplicativos de front-end. Eles nos salvaram especialmente de bugs inesperados em nossas páginas da web depois que lançamos novas alterações no código React.

Manter testes aprovados e monitorar execuções de testes com falhas em nossos ambientes de teste resulta em menos tíquetes de suporte e clientes mais satisfeitos na produção. Manter um conjunto saudável e estável de testes Cypress em execução quando você envia novas alterações de código fornece maior confiança de que as coisas estão funcionando bem e recomendamos que você e suas equipes façam o mesmo com seus testes Cypress.

Para obter mais recursos sobre testes Cypress, confira os seguintes artigos:

  • O que considerar ao escrever testes E2E
  • Visão geral de 1.000 pés para escrever testes de cipreste
  • TypeScript Todas as coisas em seus testes Cypress
  • Lidando com fluxos de e-mail em testes Cypress
  • Ideias para configurar, organizar e consolidar seus testes Cypress