Lançamos o contêiner com testes de unidade no Azure DevOps (VSTS)

Com o advento do .Net Core, temos uma grande oportunidade de não apenas executar nosso código em diferentes sistemas operacionais, mas também testá-lo em diferentes sistemas operacionais. E o que poderia ser melhor que o Docker ao trabalhar com sistemas operacionais diferentes?

O teste é mais valioso quando você não tem diferença entre o ambiente de teste e os ambientes de destino. Imagine que você suporta seu aplicativo em vários sistemas operacionais ou versões de um sistema operacional. Com o Docker, você pode testar seu aplicativo em cada um deles.

Neste artigo, veremos como criar uma imagem separada na qual os testes de unidade do seu aplicativo serão iniciados e configurados para todo esse pipeline de CI / CD no VSTS, que é o Azure DevOps recentemente.

Se você trabalha com o Docker, provavelmente está usando compilações de vários estágios para criar seus contêineres. Nesse caso, você combina a criação de binários (usando a imagem de construção) e a criação da imagem final (usando a imagem de tempo de execução) no mesmo arquivo do Docker.

Se o seu sistema consistir em um contêiner, nesse caso, a abordagem mais comum pode ser executar testes como parte do processo de construção da imagem final. Ou seja, executando testes no Dockerfile.

Para fazer isso em um processo de várias etapas, ao iniciar a docker build execute os testes como outra etapa na criação da imagem final. Vejamos um exemplo simples. Digamos que temos dois projetos: aplicativos da web e testes de unidade:


Por enquanto, não vamos nos preocupar com o que o aplicativo da web faz. Por outro lado, temos o único teste que verifica o comportamento do GuidProvider e fica assim:

 [Fact] public void Never_return_a_empty_guid() { // Arrange & Act var provider = new GuidProvider(); var id = provider.Id; // Assert Assert.NotEqual(Guid.Empty, id); } 

Agora crie um Dockerfile que criará a imagem WebApplication e executará os testes ao mesmo tempo:

 FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base WORKDIR /app EXPOSE 80 FROM microsoft/dotnet:2.1-sdk AS build WORKDIR /src COPY CiCd.sln . COPY WebApplication/WebApplication.csproj WebApplication/ COPY WebApplication.Test/WebApplication.Test.csproj WebApplication.Test/ RUN dotnet restore COPY . . WORKDIR /src/WebApplication RUN dotnet build --no-restore -c Release -o /app FROM build as test WORKDIR /src/WebApplication.Test RUN dotnet test FROM build AS publish WORKDIR /src/WebApplication RUN dotnet publish --no-build -c Release -o /app FROM base AS final WORKDIR /app COPY --from=publish /app . ENTRYPOINT ["dotnet", "WebApplication.dll"] 

Este Dockerfile deve ser colocado em um diretório com um arquivo de solução (iCd.sln). Para criar uma imagem, use o comando:

 docker build -t webapplication . 

Nosso teste falha (um erro no GuidProvider que sempre retorna Guid.Empty ); portanto, a criação da imagem falhará:

saída
 Step 15/22 : RUN dotnet test ---> Running in 423c27696356 Build started, please wait... Build completed. Test run for /src/WebApplication.Test/bin/Debug/netcoreapp2.1/WebApplication.Test.dll(.NETCoreApp,Version=v2.1) Microsoft (R) Test Execution Command Line Tool Version 15.9.0 Copyright (c) Microsoft Corporation. All rights reserved. Starting test execution, please wait... [xUnit.net 00:00:00.96] WebApplication.Test.GuidProviderTests.Never_return_a_empty_guid [FAIL] Failed WebApplication.Test.GuidProviderTests.Never_return_a_empty_guid Error Message: Assert.NotEqual() Failure Expected: Not 00000000-0000-0000-0000-000000000000 Actual: 00000000-0000-0000-0000-000000000000 Stack Trace: at WebApplication.Test.GuidProviderTests.Never_return_a_empty_guid() in /src/WebApplication.Test/GuidProviderTests.cs:line 17 Test Run Failed. Total tests: 1. Passed: 0. Failed: 1. Skipped: 0. Test execution time: 2.8166 Seconds The command '/bin/sh -c dotnet test' returned a non-zero code: 1 

Agora vamos ver como iniciar esse processo no Azure DevOps.

Nossa definição de compilação no momento é uma tarefa do tipo Docker:



Como resultado do lançamento, a construção falha porque nosso teste cai. Além disso, não temos resultados de teste (a guia "Teste" está vazia), pois o teste não é realizado no entendimento do VSTS:



A execução de testes como parte de um conjunto de imagens não é totalmente ruim, mas impedirá o VSTS de saber qual foi o resultado. Isso ocorre devido à “limitação” do Docker, que não permite a criação de volumes durante a docker build , portanto, não podemos fornecer um arquivo com resultados de teste (que podem ser gerados usando o dotnet test ), esse arquivo permanece em um contêiner intermediário e não é possível obtê-lo facilmente ele de lá.

Adotaremos uma abordagem diferente e usaremos uma ótima alternativa para docker run . Primeiro, vamos criar um contêiner separado e executar os testes nele. Para os dois contêineres, podemos usar o mesmo Dockerfile. Antes de tudo, precisamos remover a linha que executa o dotnet test do Dockerfile, já que agora os executaremos separadamente. Ok, agora vamos usar o docker run , que permite executar o Dockerfile em um ponto específico. No nosso caso, esta é a fase de teste:

 docker build -t webapplication-tests . --target test 

O parâmetro -target indica qual estágio montar. Observe que a imagem gerada será chamada " webapplication-tests ". Agora podemos executar nossos testes e salvar o arquivo " test-results.trx " com os resultados de sua execução no diretório " tests " do contêiner:

 docker run -v/c/tests:/tests webapplication-tests --entrypoint "dotnet test --logger trx;LogFileName=/tests/test-results.trx" 

Aqui, executamos a imagem criada na etapa anterior e, por meio disso, mapeamos o diretório " tests " do contêiner para o diretório host (no meu caso, D: \ CiCD \ tests). Como resultado, obtive resultados de testes em D: \ CiCD \ tests.

Para criar a imagem final, execute:

 docker build -t webapplication . 

A vantagem é que, graças ao modelo de nível do Docker, não é necessário executar novamente todas as outras etapas (ou seja, não é necessário recompilar o aplicativo).

Bem, agora vamos aplicar tudo isso aos pipelines do Azure DevOps. Para simplificar a montagem e evitar um grande número de parâmetros, usaremos o docker-compose. Nosso docker-compose.yml possui o seguinte conteúdo:

 version: '3.5' services: webapplication: image: webapplication build: context: . dockerfile: Dockerfile webapplication-tests: image: webapplication-tests build: context: . dockerfile: Dockerfile target: test 

Aqui, definimos duas imagens (webapplication e webapplication-tests). Para que tudo esteja de acordo com o cânon, vamos adicionar o arquivo docker-compose.override.yml:

 version: '3.5' services: webapplication: environment: - ASPNETCORE_ENVIRONMENT=Development ports: - "8080:80" webapplication-tests: entrypoint: - dotnet - test - --logger - trx;LogFileName=/tests/test-results.trx volumes: - ${BUILD_ARTIFACTSTAGINGDIRECTORY:-./tests/}:/tests 

Ótimo, agora para executar os testes, precisamos apenas:

 docker-compose run webapplication-tests 

Este comando executa os testes e cria o arquivo trx de saída no diretório especificado pela variável de ambiente BUILD_ARTIFACTSTAGINGDIRECTORY ou o valor padrão ./tests . A imagem final é feita assim:

 docker-compose build webapplication 

Agora você pode editar nosso processo de IC no Azure DevOps. Para fazer isso, definimos as seguintes etapas:

  1. Colete todas as imagens [build]
  2. Executar testes de unidade [executar]
  3. Publicar resultado do teste [publicar]
  4. Executar imagens no repositório (Registro) [push]

Vamos começar com a primeira etapa, que é a tarefa Docker Compose (tarefa) no Azure:



Colocamos Action: Build service images e especificamos o caminho para o docker-compose.yml.

Em seguida, execute o contêiner com testes de unidade:



Aqui você precisa selecionar Action: Run a specific service image e especificar o nome do contêiner Nome do Service Name: webapplication-tests . Além disso, não esqueça o caminho para o docker-compose.yml e o docker-compose.override.yml. O valor para Run in Background Segundo Run in Background não deve ser definido, caso contrário, o contêiner iniciará no "Modo Desconectado" e a tarefa não aguardará os resultados dos testes e passará para a próxima etapa. A tarefa Publicar Resultados do Teste tentará publicar resultados que ainda não estão disponíveis, pois a execução de testes leva tempo.

A terceira etapa é "Publicar resultados do teste":



É importante especificar Run this task: Even if a previous task has failed, unless the build was canceled . Essa opção é importante porque, caso contrário, os resultados nunca serão publicados se os testes falharem. Search folder: $(Build.ArtifactStagingDirectory)

O passo final será colocar as imagens no armazenamento. Para fazer isso, especifique a assinatura do Azure, bem como o Registro de Contêiner do Azure. Tudo está pronto para criar uma nova compilação. Salve. Começamos. Se os testes falharem, a construção falhará, mas agora vemos os resultados no VSTS:



Espero que este material tenha sido útil. Você pode encontrar meu arquivo yml de configuração de montagem aqui .

Obrigado pela atenção!

Source: https://habr.com/ru/post/pt430958/


All Articles