Wir starten den Container mit Komponententests in Azure DevOps (VSTS)

  • Tutorial
Mit dem Aufkommen von .Net Core haben wir eine großartige Gelegenheit, unseren Code nicht nur auf verschiedenen Betriebssystemen auszuführen, sondern auch auf verschiedenen Betriebssystemen zu testen. Und was kann besser sein als Docker, wenn Sie mit verschiedenen Betriebssystemen arbeiten?

Tests sind wertvoller, wenn Sie keinen Unterschied zwischen der Testumgebung und den Zielmedien haben. Stellen Sie sich vor, Sie unterstützen Ihre Anwendung auf mehreren Betriebssystemen oder Versionen des Betriebssystems. Mit Docker können Sie Ihre Anwendung in jedem von ihnen testen.

In diesem Artikel wird beschrieben, wie Sie ein separates Image erstellen, in dem die Unit testet, dass Ihre Anwendung ausgeführt wird. Konfigurieren Sie dazu eine CI / CD-Pipeline in VSTS (Azure DevOps), die seit einiger Zeit verwendet wird.

Wenn Sie mit Docker arbeiten, verwenden Sie wahrscheinlich mehrstufige Builds zum Erstellen Ihrer Container. In diesem Fall kombinieren Sie die Erstellung von Binärdateien (mithilfe des Build-Images) und die Erstellung des endgültigen Images (mithilfe des Laufzeit-Images) in derselben Docker-Datei.

Wenn Ihr System aus einem einzigen Container besteht, kann in diesem Fall der Test am häufigsten als Teil des Prozesses zum Erstellen des endgültigen Images ausgeführt werden. Das ist der Start von Tests in der Dockerfile.

Um dies in einem mehrstufigen Prozess docker builddurchzuführen , führen Sie beim Start Tests als einen weiteren Schritt beim Erstellen des endgültigen Images aus. Schauen wir uns ein einfaches Beispiel an. Angenommen, wir haben zwei Projekte: Webanwendungen und Komponententests:


Im Moment machen wir uns keine Gedanken darüber, was die Webanwendung macht. Auf der anderen Seite haben wir einen einzigen Test, der das Verhalten überprüft GuidProvider und folgendermaßen aussieht:

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

Erstellen Sie nun eine Docker-Datei, die ein WebApplication-Image erstellt und die Tests gleichzeitig ausführt:

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

Diese Docker-Datei sollte im Verzeichnis mit der Lösungsdatei (СiCd.sln) abgelegt werden. Um ein Image zu erstellen, verwenden Sie den Befehl:

docker build -t webapplication .

Unser Test schlägt fehl (ein Fehler, bei GuidProvider dem er immer zurückgegeben wird Guid.Empty), daher schlägt die Image-Erstellung fehl:

Ausgabe

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

Sehen wir uns nun an, wie Sie diesen Prozess in Azure DevOps ausführen.

Derzeit ist unsere Builddefinition eine einzelne Task vom Typ „Docker“:



Als Ergebnis des Starts schlägt der Build fehl, da der Test fehlschlägt. Darüber hinaus verfügen wir nicht über Testergebnisse (die Registerkarte Test ist leer), da beim Verständnis von VSTS keine



Tests durchgeführt werden: Das Ausführen von Tests als Teil einer Image-Assembly ist nicht so schlecht, aber VSTS kann das Ergebnis nicht erkennen. . Dies liegt an der "Einschränkung" von Docker, die es nicht erlaubt, Volumes rechtzeitig zu erstellen. Daher docker buildkönnen wir keine Datei mit Testergebnissen bereitstellen (die mithilfe von generiert werden können dotnet test). Diese Datei verbleibt in einem Zwischencontainer und kann nicht leicht von dort abgerufen werden.

Wir werden einen anderen Ansatz wählen und eine ausgezeichnete Alternative verwenden docker run. Zuerst heben wir den separaten Behälter an und beginnen die Tests darin. Für beide Container können wir dieselbe Dockerfile verwenden. Zunächst müssen Sie die dotnet testaus der Dockerfile gestartete Zeile löschen , da wir sie jetzt separat ausführen. Ok, jetzt wollen wir den Befehl verwenden docker run, mit dem Sie die Docker-Datei vor einer bestimmten Stufe ausführen können. In unserem Fall ist dies die Testphase:

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

Der Parameter -targetgibt an, welche Stufe gesammelt werden soll. Beachten Sie, dass das generierte Image " webapplication-tests " genannt wird. Jetzt können Sie unsere Tests ausführen und gleichzeitig die Datei " test-results.trx " mit den Ergebnissen ihrer Ausführung im Verzeichnis " tests " des Containers speichern :

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

Hier führen wir das im vorherigen Schritt erstellte Image aus und ordnen das Volume " tests " des Containers über das Volume mit dem Verzeichnis des Hosts überein (in meinem Fall D: \ CiCD \ tests). Als Ergebnis wurden Testergebnisse in meinem D: \ CiCD \ -Tests angezeigt.

Um den endgültigen Image-Lauf zu erstellen:

docker build -t webapplication . 

Der Vorteil ist, dass dank des Docker-Schichtenmodells keine weiteren Schritte mehr ausgeführt werden müssen (dh, die Anwendung muss nicht neu kompiliert werden).

Nun, lassen Sie uns all dies jetzt auf die Azure DevOps-Pipelines anwenden. Um die Erstellung zu vereinfachen und eine große Anzahl von Parametern zu vermeiden, verwenden wir Docker-Compose. Unser docker-compose.yml hat folgenden Inhalt:

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

Hier definieren wir zwei Bilder (Webapplication und Webapplication-Tests). Damit alles dem Kanon entspricht, fügen wir die Datei docker-compose.override.yml hinzu:

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

Toll, jetzt müssen wir nur noch die Tests durchführen:

docker-compose run webapplication-tests

Dieser Befehl führt die Tests aus und erstellt die trx-Ausgabedatei in dem durch die Umgebungsvariable angegebenen Verzeichnis BUILD_ARTIFACTSTAGINGDIRECTORYoder der Standardwert wird verwendet ./tests. Das endgültige Bild wird so gemacht:

docker-compose build webapplication

Jetzt können Sie unseren CI-Prozess in Azure DevOps bearbeiten. Dazu definieren wir folgende Schritte:

  1. Sammle alle Bilder [Build]
  2. Unit-Tests ausführen [run]
  3. Testergebnis veröffentlichen [Publizieren]
  4. Bilder in den Speicher verschieben (Registry) [Push]

Wir beginnen mit dem ersten Schritt, der eine neue Aufgabe (Task) Docker Compose in Azure stellt:



Setzen Action: Build service imagesund weist den Weg zu compose.yml Andockfenster.

Führen Sie dann den Container mit Komponententests aus:



Hier müssen Sie Action: Run a specific service imageden Namen des Containers auswählen und angeben Service Name: webapplication-tests. Vergessen Sie auch nicht den Pfad zu docker-compose.yml und docker-compose.override.yml. Der Wert für Run in Backgrounddarf nicht gesetzt sein, andernfalls wird der Container im getrennten Modus gestartet, und die Task wartet nicht auf die Testergebnisse, sondern fährt mit dem nächsten Schritt fort. Die Aufgabe "Testergebnisse veröffentlichen" versucht, Ergebnisse zu veröffentlichen, die möglicherweise noch nicht vorhanden sind, da der Start von Tests einige Zeit in Anspruch nimmt.

Der dritte Schritt ist „Testergebnisse veröffentlichen“:



Es ist wichtig anzugeben Run this task: Even if a previous task has failed, unless the build was canceled. Dieser Parameter ist wichtig, da die Ergebnisse sonst nur dann veröffentlicht werden, wenn die Tests bestanden werden. Search folder: $(Build.ArtifactStagingDirectory)

Im letzten Schritt werden die Bilder in das Repository verschoben. Dazu müssen Sie das Azure-Abonnement sowie die Azure-Container-Registrierung angeben. Alles ist bereit, um einen neuen Build zu erstellen. Wir sparen Wir fangen an. Wenn die Tests fehlschlagen, schlägt der Build fehl, aber jetzt sehen wir die Ergebnisse in VSTS:



Ich hoffe, dass dieses Material nützlich war. Sie finden meine Yml-Konfigurationsdatei hier .

Vielen Dank für Ihre Aufmerksamkeit!

Jetzt auch beliebt: