Devo incluir testes na imagem do Docker?

18

Quando se trata de testes, posso pensar em duas opções:

  1. Coloque teste e aplicação em uma imagem.
  2. Inclua apenas o código do aplicativo na imagem. Crie um contêiner específico de teste que seja construído após a imagem principal e adicione algumas camadas (código de teste, dependências etc.).

Com a primeira opção, posso testar o contêiner e enviá-lo exatamente como testado. Uma desvantagem óbvia é que código desnecessário (e potencialmente dados de teste) serão incluídos na imagem.

Com a segunda opção, a imagem enviada não é a mesma que a testada.

Ambos parecem más estratégias. Existe uma terceira estratégia melhor?

lfk
fonte
1
Você basicamente respondeu a si mesmo. Ambos são uma má ideia. Você enviará os processos executáveis ​​já testados para um contêiner dimensionado e personalizado de acordo com as necessidades. Você não quer dependências de desenvolvimento nem código src. Na produção é considerado um risco.
LAIV
1
Testar antes da conteinerização significa que o ambiente não é testado, apenas o código. Você testou apenas parte do que está enviando, e não tudo.
Lfk

Respostas:

10

Para executar testes em tempo de construção, a maneira preferida seria usar uma construção em vários estágios . Os Dockerfiles com vários estágios permitem que você tenha um estágio maior com todas as dependências para construção e teste e copie os artefatos exatos que você testou em outro estágio para obter uma imagem de tempo de execução menor.

Você também deseja testes no nível do sistema de vários contêineres, usando suas interfaces externas em vez de executar dentro do contêiner. Como esses testes envolvem coordenação entre serviços, exigem dependências diferentes, como acesso à sua orquestração, não são tão completos quanto os testes em tempo de compilação e, geralmente, são escritos em idiomas completamente diferentes, não é grande coisa executá-los em um Docker separado recipiente dedicado apenas ao teste do sistema.

Karl Bielefeldt
fonte
1
Portanto, essa é basicamente a opção 2 - eu executo os testes em um ambiente / contêiner muito semelhante à produção, mas não exatamente o mesmo. Isso está certo?
Lfk
9

Existe uma terceira maneira, como você mesmo disse. Eu acho que você está misturando desenvolvimento, teste e implantação. Proponho que todo o SDLC seja visto como um todo, primeiro, para entender o que você está tentando alcançar. Este é um tópico importante, mas farei o possível para resumir.

TL; DR;

Em resumo, você precisa separar:

  • seu código, de
  • a configuração do aplicativo, de
  • a configuração do ambiente do sistema.

Cada um precisa ser independente um do outro e adequadamente:

  • versão controlada
  • testado
  • implantável

Versão Longa

Primeiro, você tem um aplicativo composto de código e (conjuntos separados de) configuração. Isso precisa ser testado, tanto para as funções de compilação quanto para as intencionais - isso é chamado de integração contínua (IC). Existem muitos provedores desse serviço on-line e localmente - por exemplo, CircleCI para um provedor de nuvem que se vincula ao seu repositório e cria e testa sempre que você confirma. Se o seu repositório estiver no local e não puder usar um provedor de nuvem, algo como Jenkinsseria um equivalente. Se seu aplicativo for bastante padrão, provavelmente existe uma imagem do Docker existente que o serviço de IC pode usar. Caso contrário, você precisará criar um, ou um cluster, para que o código e a configuração do aplicativo possam ser implantados. Configurado corretamente, você terá várias estatísticas sobre a qualidade do código do seu aplicativo.

Em seguida, assim que estiver satisfeito com a funcionalidade e a correção do seu aplicativo, a base de código deve ser devidamente identificada para uma versão específica. Essa construção deve ser implantada em um ambiente de teste. Observe que o código será o mesmo que o testado no seu IC (provavelmente, se você fez isso corretamente), mas sua configuração pode ser diferente. Novamente, alguns provedores de IC podem oferecer esta etapa para que você possa testar sua implantação de um aplicativo em pacote e uma configuração discreta. Esse estágio normalmente inclui testes funcionais do usuário (para novas funcionalidades), bem como testes automatizados (para funcionalidades conhecidas). Se a liberação passar neste estágio, você terá um candidato à liberação para teste de integração. Você pode executar os testes de automação de outro contêiner do Docker,algumas métricas que afirmam que o esforço de teste é 1: 1 para o esforço de codificação (embora eu não tenha certeza disso).

Penultimamente, o próximo passo é onde você cria seu ambiente (sistema) como se fosse produção. Se você estiver usando o Docker em produção, é aqui que você pensará em proteção de segurança, otimização de rede e servidor etc. Suas imagens do Docker podem se basear nas que você usou no Development (idealmente), mas pode haver alterações no dimensionamento e na segurança , como eu disse. Até agora o teste funcional do aplicativo deve estar completo, você está mais preocupado com segurança e desempenho. De acordo com o teste funcional, seus testes aqui podem ser desenvolvidos, implantados e executados a partir de outras imagens do Docker. Essa etapa costumava ser terrivelmente cara e raramente era feita para você precisar de um hardware dedicado que reproduzisse a produção. Hoje, isso é completamente viável, pois você pode se levantar e derrubar todo o ambiente de praticamente qualquer escala sob demanda.

Por fim, você tem uma versão que deve estar pronta para produção com apenas um pequeno conjunto de deltas de configuração do teste de integração (endereços IP, URIs de banco de dados, senhas etc.). Sua base de código foi testada pelo menos em três ambientes diferentes neste momento. ponto e a maioria da configuração do sistema pelo menos uma vez.

avastmick
fonte
Isso significa que seu IC não estará testando seus Dockerfiles? Por exemplo, se seu Dockerfile estivesse sem uma dependência, os testes ainda passariam?
Lfk
1
De modo nenhum. Primeiro teste o código, depois teste a configuração do aplicativo e depois teste o sistema. O que estou dizendo é que essas são atividades discretas. O melhor da conteinerização é que o sonho de desenvolvimento em um ambiente que é o mesmo que prod está muito próximo. Mas o endurecimento tornaria o desenvolvimento muito difícil.
Avastmick 27/01/19
0

Eu acho que você está misturando diferentes tipos de testes. Basicamente, você precisa se perguntar: Qual é a unidade em teste aqui?

O cenário mais comum quando você trabalha como desenvolvedor é escrever testes de unidade / integração para algum trecho de código em que está trabalhando, onde esse trecho de código é a unidade em teste. Você executa esses testes localmente e / ou no IC.

Quando você cria uma nova imagem do Docker, ela se torna uma nova unidade que você pode testar. Que tipo de coisas você gostaria de testar para esta imagem? Qual é a API que está fornecendo? Como você testa isso?

Se for um aplicativo da web, você poderá iniciar um contêiner com base na imagem, fazer algumas solicitações HTTP e verificar se as respostas são as esperadas. O problema que acho que está ocorrendo é que você está muito acostumado à estrutura de teste que está sendo acoplada ao código do aplicativo. Isso é bom durante o desenvolvimento, mas agora você deseja testar uma imagem do docker e, portanto, precisa de um novo tipo de estrutura de teste que possa fazer isso e que não esteja vinculado ao código do aplicativo.

Então eu acho que a terceira opção que você está procurando é:

  • Execute seus testes de unidade / integração antes de criar uma imagem do docker.
  • Crie uma imagem de janela de encaixe contendo apenas o aplicativo que você deseja distribuir.
  • Em vez de adicionar camadas adicionais sobre a imagem do aplicativo, teste-a como está executando-a com alguns parâmetros e confirme as saídas esperadas.

Portanto, as etapas de CI / CD seriam:

Ambiente de desenvolvimento da instalação -> Executar testes no código -> Criar imagem final -> Executar testes na imagem -> Implementar imagem.

Lars Nyström
fonte