Nous lançons le conteneur avec des tests unitaires dans Azure DevOps (VSTS)

Avec l'avènement de .Net Core, nous avons une excellente occasion non seulement d'exécuter notre code sur différents systèmes d'exploitation, mais aussi de le tester sur différents systèmes d'exploitation. Et quoi de mieux que Docker lorsque vous travaillez avec différents systèmes d'exploitation?

Les tests sont plus utiles lorsque vous n'avez aucune différence entre l'environnement de test et les environnements cibles. Imaginez que vous preniez en charge votre application sur plusieurs systèmes d'exploitation ou versions d'un système d'exploitation. Avec Docker, vous pouvez tester votre application dans chacun d'eux.

Dans cet article, nous verrons comment créer une image distincte dans laquelle les tests unitaires de votre application seront lancés et configurer pour tout ce pipeline CI / CD dans VSTS qui est Azure DevOps récemment.

Si vous travaillez avec Docker, vous utilisez probablement des builds en plusieurs étapes pour construire vos conteneurs. Dans ce cas, vous combinez la création de binaires (en utilisant l'image de construction) et la création de l'image finale (en utilisant l'image d'exécution) dans le même fichier Docker.

Si votre système se compose d'un seul conteneur, dans ce cas, l'approche la plus courante peut être d'exécuter des tests dans le cadre du processus de création de l'image finale. Autrement dit, exécuter des tests dans le Dockerfile.

Pour ce faire dans un processus en plusieurs étapes, lorsque vous lancez la docker build vous exécutez les tests comme une autre étape de la création de l'image finale. Regardons un exemple simple. Disons que nous avons deux projets: les applications web et les tests unitaires:


Pour l'instant, ne nous inquiétons pas de ce que fait l'application Web. D'un autre côté, nous avons le seul test qui vérifie le comportement de GuidProvider et ressemble à ceci:

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

Créez maintenant un Dockerfile qui créera l'image WebApplication et exécutera les tests en même temps:

 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"] 

Ce Dockerfile doit être placé dans un répertoire avec un fichier de solution (iCd.sln). Pour créer une image, utilisez la commande:

 docker build -t webapplication . 

Notre test échoue (une erreur dans GuidProvider qui renvoie toujours Guid.Empty ), donc la construction de l'image échouera:

sortie
 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 

Voyons maintenant comment démarrer ce processus dans Azure DevOps.

Notre définition de build pour le moment est une tâche de type Docker:



À la suite du lancement, la version échoue car notre test échoue. De plus, nous n'avons pas de résultats de test (l'onglet "Test" est vide), car le test n'est pas effectué dans la compréhension de VSTS:



L'exécution de tests dans le cadre d'un assemblage d'images n'est pas entièrement mauvaise, mais elle empêchera VSTS de savoir quel a été le résultat. Cela est dû à la «limitation» de Docker, qui ne permet pas de créer des volumes pendant la docker build , par conséquent, nous ne pouvons pas fournir un fichier avec les résultats des tests (qui peuvent être générés à l'aide dotnet test ), ce fichier reste dans un conteneur intermédiaire, et nous ne pouvons pas facilement l'obtenir lui de là.

Nous adopterons une approche différente et utiliserons une excellente alternative à la docker run . Tout d'abord, levons un conteneur séparé et exécutons les tests qu'il contient. Pour les deux conteneurs, nous pouvons utiliser le même Dockerfile. Tout d'abord, nous devons supprimer la ligne qui exécute le dotnet test du Dockerfile, car nous allons maintenant les exécuter séparément. Ok, utilisons maintenant la docker run , qui vous permet d'exécuter le Dockerfile à un point spécifique. Dans notre cas, c'est la phase de test:

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

Le paramètre -target indique quelle étape assembler. Veuillez noter que l'image générée sera appelée " webapplication-tests ". Nous pouvons maintenant exécuter nos tests et enregistrer le fichier " test-results.trx " avec les résultats de leur exécution dans le répertoire " tests " du conteneur:

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

Ici, nous exécutons l'image créée à l'étape précédente, et à travers cela, nous mappons le répertoire " tests " du conteneur vers le répertoire hôte (dans mon cas D: \ CiCD \ tests). Par conséquent, j'ai obtenu les résultats des tests dans D: \ CiCD \ tests.

Afin de construire l'image finale, exécutez:

 docker build -t webapplication . 

L'avantage est que grâce au modèle de niveau Docker, il n'est pas nécessaire de réexécuter toutes les autres étapes (c'est-à-dire qu'il n'est pas nécessaire de recompiler l'application).

Eh bien, appliquons maintenant tout cela aux pipelines Azure DevOps. Pour simplifier l'assemblage et éviter un grand nombre de paramètres, nous utiliserons docker-compose. Notre docker-compose.yml a le contenu suivant:

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

Nous définissons ici deux images (webapplication et webapplication-tests). Pour que tout soit conforme au canon, ajoutons le fichier 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 

Génial, maintenant, pour exécuter les tests, il nous suffit de:

 docker-compose run webapplication-tests 

Cette commande exécute les tests et crée le fichier trx de sortie dans le répertoire spécifié par la variable d'environnement BUILD_ARTIFACTSTAGINGDIRECTORY ou la valeur par défaut ./tests . L'image finale se fait comme ceci:

 docker-compose build webapplication 

Vous pouvez maintenant modifier notre processus CI dans Azure DevOps. Pour ce faire, nous définissons les étapes suivantes:

  1. Collectionnez toutes les images [build]
  2. Exécuter des tests unitaires [exécuter]
  3. Publier le résultat du test [publier]
  4. Exécuter des images dans le référentiel (registre) [push]

Commençons par la première étape, qui est la tâche Docker Compose (tâche) dans Azure:



Nous avons mis Action: Build service images et spécifier le chemin d'accès à docker-compose.yml.

Ensuite, exécutez le conteneur avec des tests unitaires:



Ici, vous devez sélectionner Action: Run a specific service image et spécifier le nom du conteneur Nom du Service Name: webapplication-tests . N'oubliez pas non plus le chemin d'accès à docker-compose.yml et docker-compose.override.yml. La valeur de Run in Background ne doit pas être définie, sinon le conteneur démarrera en "mode détaché" et la tâche n'attendra pas les résultats des tests et passera à l'étape suivante. La tâche de publication des résultats de test tentera de publier des résultats qui ne sont peut-être pas encore disponibles, car l'exécution des tests prend du temps.

La troisième étape est «Publier les résultats des tests»:



Il est important de spécifier Run this task: Even if a previous task has failed, unless the build was canceled . Cette option est importante car sinon les résultats ne seront jamais publiés si les tests échouent. Search folder: $(Build.ArtifactStagingDirectory)

La dernière étape consistera à pousser les images dans le stockage. Pour ce faire, spécifiez l'abonnement Azure, ainsi que le registre de conteneurs Azure. Tout est prêt pour créer une nouvelle construction. Enregistrez. Nous commençons. Si les tests échouent, la construction échouera, mais maintenant nous voyons les résultats dans VSTS:



J'espère que ce matériel a été utile. Vous pouvez trouver mon fichier yml de configuration d'assemblage ici .

Merci de votre attention!

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


All Articles