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() {
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:
- Collectionnez toutes les images [build]
- Exécuter des tests unitaires [exécuter]
- Publier le résultat du test [publier]
- 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!