paint-brush
Configurando um ambiente de ponta a ponta perfeitamente isoladopor@marcinwosinek
511 leituras
511 leituras

Configurando um ambiente de ponta a ponta perfeitamente isolado

por Marcin Wosinek5m2023/04/12
Read on Terminal Reader

Muito longo; Para ler

Testes flaky são testes que falham por motivos não relacionados ao seu código. Em casos extremos, testes esquisitos ensinarão sua equipe a ignorar os resultados do E2E. Isso pode eliminar o esforço de automatizar o controle de qualidade (QA). A abordagem apresentada aqui trata de duas grandes fontes de possíveis problemas em suas execuções de teste.
featured image - Configurando um ambiente de ponta a ponta perfeitamente isolado
Marcin Wosinek HackerNoon profile picture

Para testes end-to-end (E2E) estáveis, precisamos de um ambiente o mais isolado possível do exterior.

Reduzir a descamação

Testes flaky são testes que falham por motivos não relacionados ao seu código. Eles dificultam o uso do E2E como uma verificação confiável da exatidão do aplicativo. Em casos extremos, testes esquisitos ensinarão sua equipe a ignorar os resultados do E2E. Isso pode matar o esforço de automatizar o controle de qualidade (QA).


A abordagem apresentada aqui aborda duas grandes fontes de possíveis problemas em suas execuções de teste:


  • Estado armazenado pelo back-end compartilhado por diferentes trabalhos de teste e


  • Serviços externos sobre os quais você não tem controle.


Existem outras fontes de descamação não afetadas por essa abordagem:


  • O verdadeiro problema está no aplicativo que apareceu aleatoriamente ou


  • Os problemas no aplicativo são causados pela velocidade não natural com que o E2E interage com ele.

Alternativa

Antes de minha equipe e eu executarmos meus testes em um contêiner de back-end dedicado, usamos um de nossos servidores que não são de produção. Essa abordagem funcionou bem no estágio de experimentação de nossa solução E2E.


Quando havia apenas alguns testes, não podíamos usar os resultados dos testes para tomar decisões de qualquer maneira.


No entanto, conforme continuamos adicionando mais testes e gerando tempos de execução mais longos, essa abordagem começou a desmoronar. As principais questões foram as seguintes:


  • Mesmo tentando reverter as mudanças de dados dentro do teste, algumas falhas de teste estavam deixando para trás mudanças inesperadas.


  • Trabalhos paralelos estavam colidindo. Tarefas de teste diferentes estavam alterando os mesmos estados, o que frequentemente fazia com que uma das tarefas falhasse.

Dockerizar tudo

Uma solução para esse problema foi dedicar um servidor de back-end e um banco de dados separados para cada tarefa de teste. Essa abordagem seria muito desafiadora se não fosse pelo Docker.


Os contêineres do Docker são uma ferramenta perfeita para criar um ambiente contido com tudo o que é necessário para executar um aplicativo:


  • O sistema operacional certo (ou melhor, a distribuição correta do Linux),


  • as dependências do sistema, como bibliotecas de manipulação de imagens, etc., e


  • A versão correta dos intérpretes de linguagem (Python, Node, etc.) ou servidores de banco de dados.

Base de dados

Para seu teste, você pode preparar um contêiner de banco de dados dedicado que vem com dados de teste previsíveis. Dessa forma, você poderá reproduzir exatamente o ponto de partida em cada execução do E2E, tornando seus testes mais estáveis.


Você pode usar tags diferentes para sua imagem do Docker, para controle de versão do banco de dados de teste. O mesmo banco de dados de teste também pode ser usado em um ambiente de desenvolvimento. Para testes manuais em desenvolvimento, você precisa de entidades de exemplo semelhantes às dos testes automatizados.

Processo interno

Se você já usou o Docker para implantar seu back-end, será muito fácil reutilizar a mesma imagem para executar seu E2E. Em minha equipe, implantamos um back-end como contêineres e fornecemos URLs e credenciais de banco de dados como variáveis de ambiente.


A mesma versão do contêiner pode ser implantada na produção ou usada na integração contínua (CI) para executar testes – cada ambiente fornece os valores corretos para conexão com o banco de dados.

Front-end

Dependendo da sua estratégia de implantação, você pode fazer um dos seguintes:


  1. Use os contêineres que você cria como parte da compilação do front-end.


  2. Obtenha os arquivos compilados e verifique se eles estão disponíveis via HTTP para os testes.


No nosso caso, usamos a opção 2: implantamos o aplicativo como arquivos estáticos, então criamos um contêiner dedicado para servir os arquivos construídos durante as execuções do trabalho E2E.

Serviços de trabalho no GitLab

Usamos o GitLab como plataforma para executar nosso CI. Cada trabalho no GitLab é executado dentro de um contêiner com uma imagem de sua escolha. Além do container principal, você pode definir serviços : Containers adicionais rodando junto com seus testes. A configuração é tão fácil quanto:

 <job-name>: services: - name: <image> alias: <container-url>


As opções disponíveis são semelhantes às que você tem no Docker Compose, mas são mais limitadas.

Uma “pegadinha” na configuração do GitLab é definir a variável FF_NETWORK_PER_BUILD como 1 se você quiser permitir que os serviços acessem uns aos outros durante a execução do teste.

Considere dados ad hoc para isolamento no trabalho

Em algum momento, estávamos executando todos os testes em paralelo dentro de um trabalho. Naquela época, era necessário impor um isolamento ainda mais forte – cada teste usava o mesmo back-end e banco de dados.


Para contornar esse problema, atualizamos nossos testes para depender principalmente dos dados aleatórios que injetamos dentro da seção before dos testes. Isso permitiu que os testes fossem executados sem serem afetados por outras alterações que aconteciam em outros encadeamentos.


Essa abordagem pode ser um pouco complicada no começo, mas pode fazer sentido dependendo das circunstâncias.

Limpar após cada teste

Mesmo que iniciemos um novo banco de dados para cada trabalho de teste, ainda estamos tentando fazer com que nossos testes deixem o aplicativo no mesmo estado em que o encontraram. Talvez seja um resquício do período em que fazíamos testes em um ambiente compartilhado.


Não é mais crucial, mas ainda pode ajudar durante o desenvolvimento do teste nos seguintes casos:


  • Quando você executa apenas um teste, o estado que o teste encontra não é diferente de quando você executa todos os testes no arquivo.


  • Quando você executa novamente o mesmo teste localmente várias vezes, de modo que o banco de dados não seja afetado pelas execuções anteriores

Serviço Externo Simulado

Há casos em que mover serviços para um contêiner não é uma opção. Por exemplo:


  • Se houver servidores externos que o aplicativo usa diretamente ou por meio de algum proxy de back-end, ou


  • Você possui servidores que não são possíveis de rodar dentro de um container devido a problemas técnicos.


Em ambos os casos, para isolar as execuções de teste, você pode simular as solicitações que vão para esses serviços. Isso impedirá que serviços externos imprevisíveis afetem os resultados do teste. Uma desvantagem dessa abordagem é que seus testes serão desconectados do contexto no qual seus aplicativos operam.


Com simulações em vigor, seus testes não detectarão casos em que as alterações nesses serviços afetam seu aplicativo.

Continue aprendendo

Se você estiver interessado em aprender mais sobre testes ou outros tópicos relacionados à programação, inscreva-se aqui para receber atualizações quando eu publicar conteúdo relacionado.