Übung: Ausführen von Auslastungstests in Azure Pipelines

Abgeschlossen

In diesem Abschnitt führen Sie den Testplan aus, den Sie in der Releasepipeline erstellt haben. Der Testplan verwendet Apache JMeter zum Ausführen von Auslastungstests.

So führen Sie die Tests aus:

  • Fetchen Sie einen Git-Branch, der die Tests implementiert, und checken Sie diesen aus.
  • Ändern Sie die Pipeline, damit JMeter installiert, der Testplan ausgeführt und die Ergebnisse in JUnit transformiert und in Azure Pipelines veröffentlicht werden.
  • Pushen Sie Ihren Branch an GitHub, beobachten Sie die Testausführung in Azure Pipelines, und untersuchen Sie die Ergebnisse.

Abrufen des Branchs aus GitHub

In diesem Abschnitt fetchen Sie den Branch jmeter aus GitHub und checken ihn aus oder wechseln zu ihm.

Dieser Branch enthält das Space Game-Projekt, mit dem Sie in den vorherigen Modulen gearbeitet haben. Er enthält auch eine Azure Pipelines-Konfiguration als Ausgangspunkt.

  1. Öffnen Sie in Visual Studio Code das integrierte Terminal.

  2. Führen Sie die folgenden git fetch- und git checkout-Befehle aus, um einen Branch namens jmeter aus dem Microsoft-Repository herunterzuladen und zu diesem Branch zu wechseln:

    git fetch upstream jmeter
    git checkout -B jmeter upstream/jmeter
    

    Denken Sie daran, dass sich upstream auf das Microsoft-Repository auf GitHub bezieht. Die Git-Konfiguration Ihres Projekts kann mit dem Upstreamremoterepository arbeiten, weil Sie diese Beziehung eingerichtet haben, als Sie das Projekt aus dem Repository von Microsoft geforkt und es lokal geklont haben.

    In Kürze werden Sie diesen Branch per Push in Ihr GitHub-Repository (als origin bezeichnet) übertragen.

  3. Öffnen Sie in Visual Studio Code optional die Datei azure-pipelines.yml. Überprüfen Sie die anfängliche Konfiguration.

    Die Konfiguration weist Ähnlichkeit mit den Konfigurationen auf, die Sie in den vorherigen Modulen dieses Lernpfads erstellt haben. Nur die Releasekonfiguration der Anwendung wird damit erstellt. Aus Gründen der Übersichtlichkeit werden außerdem die Trigger, manuellen Genehmigungen und Tests ausgelassen, die Sie in vorherigen Modulen eingerichtet haben.

    Hinweis

    Bei einer robusteren Konfiguration könnten die Branches angegeben werden, die am Buildprozess beteiligt sind. Beim Pushen einer Änderung in einem Branch können immer Komponententests ausgeführt werden, um z. B. die Codequalität zu überprüfen. Sie können die Anwendung auch in einer Umgebung bereitstellen, in der umfassendere Tests durchgeführt werden. Diese Bereitstellung erfolgt jedoch nur dann, wenn ein Pull Request vorhanden ist, Sie über einen Release Candidate verfügen oder Code im Branch main zusammengeführt werden soll.

    Weitere Informationen finden Sie unter Implementieren eines Codeworkflows in Ihrer Buildpipeline mithilfe von Git und GitHub und Buildpipeline-Trigger.

  4. Optional können Sie in Visual Studio Code die JMeter-Testplandatei LoadTest.jmx und die XLST-Datei JMeter2JUnit.xsl auschecken. Die XLST-Datei transformiert die JMeter-Ausgabe in JUnit, damit Azure Pipelines die Ergebnisse visualisieren kann.

Hinzufügen von Variablen zu Azure Pipelines

Der ursprüngliche Testplan des Teams enthält einen hartcodierten Wert für den Hostnamen der Website von Space Game, die in der Stagingumgebung ausgeführt wird.

Ihre Version verwendet eine JMeter-Eigenschaft, um den Testplan flexibler zu gestalten. Stellen Sie sich eine Eigenschaft als Variable vor, die Sie über die Befehlszeile festlegen können.

So wird die Variable hostname in JMeter definiert:

Screenshot of setting the hostname variable in Apache JMeter.

Hier sehen Sie, wie die Variable hostname die Funktion __P verwendet, um die Variable hostname zu lesen.

Screenshot for reading the hostname variable in Apache JMeter.

Die zugehörige Testplandatei, LoadTest.jmx, gibt diese Variable an und verwendet sie, um den Hostnamen festzulegen.

Wenn Sie JMeter über die Befehlszeile ausführen, verwenden Sie das Argument -J, um die Eigenschaft hostname festzulegen. Ein Beispiel:

apache-jmeter-5.4.3/bin/./jmeter -n -t LoadTest.jmx -o Results.xml -Jhostname=tailspin-space-game-web-staging-1234.azurewebsites.net

Hier legen Sie die Variable STAGING_HOSTNAME in Azure Pipelines fest. Diese Variable verweist auf den Hostnamen Ihrer Website, die in App Service in der Stagingumgebung ausgeführt wird. Zudem legen Sie mit jmeterVersion die zu installierende JMeter-Version fest.

Wenn der Agent ausgeführt wird, werden diese Variablen automatisch als Umgebungsvariablen in den Agent exportiert, sodass Ihre Pipelinekonfiguration JMeter auf diese Weise ausführen kann:

apache-jmeter-5.4.3/bin/./jmeter -n -t LoadTest.jmx -o Results.xml -Jhostname=$(STAGING_HOSTNAME)

Fügen Sie jetzt die Pipelinevariable hinzu, bevor Sie die Pipelinekonfiguration aktualisieren. Gehen Sie folgendermaßen vor:

  1. Navigieren Sie in Azure DevOps zum Projekt Space Game - web - Nonfunctional tests.

  2. Wählen Sie unter Pipelines die Option Library (Bibliothek) aus.

  3. Wählen Sie die Variablengruppe Release aus.

  4. Wählen Sie unter Variablen die Option + Hinzufügen aus.

  5. Geben Sie STAGING_HOSTNAME als Variablennamen ein. Geben Sie als Wert die URL der App Service Instanz ein, die der Stagingumgebung entspricht, z. B. tailspin-space-game-web-staging-1234.azurewebsites.net.

    Wichtig

    Fügen Sie nicht das Protokollpräfix http:// oder https:// in Ihren Wert ein. JMeter stellt das Protokoll bereit, wenn die Tests ausgeführt werden.

  6. Fügen Sie eine zweite Variable namens jmeterVersion hinzu. Geben Sie 5.4.3 als deren Wert an.

    Hinweis

    Diese JMeter-Version wurde zuletzt zum Testen dieses Moduls verwendet. Die aktuelle Version von Apache JMeter können Sie über die Downloadseite herunterladen.

  7. Um Ihre Variable in der Pipeline zu speichern, wählen Sie oben auf der Seite Speichern aus.

    Ihre Variablengruppe ähnelt der in der folgenden Abbildung gezeigten Gruppe:

    Screenshot of Azure Pipelines, showing the variable group. The group contains five variables.

Ändern der Pipelinekonfiguration

In diesem Abschnitt ändern Sie die Pipeline, damit die Auslastungstests während der Stagingphase ausgeführt werden.

  1. Öffnen Sie in Visual Studio Code die Datei azure-pipelines.yml. Ändern Sie dann die Datei wie folgt:

    Tipp

    Sie können die gesamte Datei ersetzen oder nur den hervorgehobenen Teil aktualisieren.

    trigger:
    - '*'
    
    variables:
      buildConfiguration: 'Release'
    
    stages:
    - stage: 'Build'
      displayName: 'Build the web application'
      jobs:
      - job: 'Build'
        displayName: 'Build job'
        pool:
          vmImage: 'ubuntu-20.04'
          demands:
          - npm
    
        variables:
          wwwrootDir: 'Tailspin.SpaceGame.Web/wwwroot'
          dotnetSdkVersion: '6.x'
    
        steps:
        - task: UseDotNet@2
          displayName: 'Use .NET SDK $(dotnetSdkVersion)'
          inputs:
            version: '$(dotnetSdkVersion)'
    
        - task: Npm@1
          displayName: 'Run npm install'
          inputs:
            verbose: false
    
        - script: './node_modules/.bin/node-sass $(wwwrootDir) --output $(wwwrootDir)'
          displayName: 'Compile Sass assets'
    
        - task: gulp@1
          displayName: 'Run gulp tasks'
    
        - script: 'echo "$(Build.DefinitionName), $(Build.BuildId), $(Build.BuildNumber)" > buildinfo.txt'
          displayName: 'Write build info'
          workingDirectory: $(wwwrootDir)
    
        - task: DotNetCoreCLI@2
          displayName: 'Restore project dependencies'
          inputs:
            command: 'restore'
            projects: '**/*.csproj'
    
        - task: DotNetCoreCLI@2
          displayName: 'Build the project - $(buildConfiguration)'
          inputs:
            command: 'build'
            arguments: '--no-restore --configuration $(buildConfiguration)'
            projects: '**/*.csproj'
    
        - task: DotNetCoreCLI@2
          displayName: 'Publish the project - $(buildConfiguration)'
          inputs:
            command: 'publish'
            projects: '**/*.csproj'
            publishWebProjects: false
            arguments: '--no-build --configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)/$(buildConfiguration)'
            zipAfterPublish: true
    
        - publish: '$(Build.ArtifactStagingDirectory)'
          artifact: drop
    
    - stage: 'Dev'
      displayName: 'Deploy to the dev environment'
      dependsOn: Build
      jobs:
      - deployment: Deploy
        pool:
          vmImage: 'ubuntu-20.04'
        environment: dev
        variables:
        - group: Release
        strategy:
          runOnce:
            deploy:
              steps:
              - download: current
                artifact: drop
              - task: AzureWebApp@1
                displayName: 'Azure App Service Deploy: website'
                inputs:
                  azureSubscription: 'Resource Manager - Tailspin - Space Game'
                  appName: '$(WebAppNameDev)'
                  package: '$(Pipeline.Workspace)/drop/$(buildConfiguration)/*.zip'
    
    - stage: 'Test'
      displayName: 'Deploy to the test environment'
      dependsOn: Dev
      jobs:
      - deployment: Deploy
        pool:
          vmImage: 'ubuntu-20.04'
        environment: test
        variables:
        - group: 'Release'
        strategy:
          runOnce:
            deploy:
              steps:
              - download: current
                artifact: drop
              - task: AzureWebApp@1
                displayName: 'Azure App Service Deploy: website'
                inputs:
                  azureSubscription: 'Resource Manager - Tailspin - Space Game'
                  appName: '$(WebAppNameTest)'
                  package: '$(Pipeline.Workspace)/drop/$(buildConfiguration)/*.zip'
    
    - stage: 'Staging'
      displayName: 'Deploy to the staging environment'
      dependsOn: Test
      jobs:
      - deployment: Deploy
        pool:
          vmImage: 'ubuntu-20.04'
        environment: staging
        variables:
        - group: 'Release'
        strategy:
          runOnce:
            deploy:
              steps:
              - download: current
                artifact: drop
              - task: AzureWebApp@1
                displayName: 'Azure App Service Deploy: website'
                inputs:
                  azureSubscription: 'Resource Manager - Tailspin - Space Game'
                  appName: '$(WebAppNameStaging)'
                  package: '$(Pipeline.Workspace)/drop/$(buildConfiguration)/*.zip'
      - job: RunLoadTests
        dependsOn: Deploy
        displayName: 'Run load tests'
        pool:
          vmImage: 'ubuntu-20.04'
        variables:
        - group: Release
        steps:
        - script: |
            wget -c archive.apache.org/dist/jmeter/binaries/apache-jmeter-$(jmeterVersion).tgz
            tar -xzf apache-jmeter-$(jmeterVersion).tgz
          displayName: 'Install Apache JMeter'
        - script: apache-jmeter-$(jmeterVersion)/bin/./jmeter -n -t LoadTest.jmx -o Results.xml -Jhostname=$(STAGING_HOSTNAME)
          displayName: 'Run Load tests'
        - script: |
            sudo apt-get update
            sudo apt-get install xsltproc
            xsltproc JMeter2JUnit.xsl Results.xml > JUnit.xml
          displayName: 'Transform JMeter output to JUnit'
        - task: PublishTestResults@2
          inputs:
            testResultsFormat: JUnit
            testResultsFiles: JUnit.xml
    

    Zusammenfassung der Änderungen:

    • Der Auftrag RunLoadTests führt einen Auslastungstest über einen Linux-Agent aus.
    • Der Auftrag RunLoadTests hängt vom Auftrag Deploy ab, damit die Aufträge in der richtigen Reihenfolge ausgeführt werden. Sie müssen die Website in App Service bereitstellen, bevor Sie die Auslastungstests ausführen können. Wenn Sie diese Abhängigkeit nicht angeben, können Aufträge innerhalb der Phase in beliebiger Reihenfolge oder parallel ausgeführt werden.
    • Der erste script-Task lädt JMeter herunter und führt die Installation durch. Die Pipelinevariable jmeterVersion gibt die zu installierende Version von JMeter an.
    • Der zweite script-Task führt JMeter aus. Das Argument -J legt die Eigenschaft hostname in JMeter fest, indem die Variable STAGING_HOSTNAME aus der Pipeline gelesen wird.
    • Der dritte script-Task installiert xsltproc, einen XSLT-Prozessor, und transformiert die JMeter-Ausgabe in JUnit.
    • Der Task PublishTestResults@2 veröffentlicht den resultierenden JUnit-Bericht, JUnit.xml, in der Pipeline. Mit Azure Pipelines können Sie die Testergebnisse visualisieren.
  2. Fügen Sie azure-pipelines.yml im integrierten Terminal zum Index hinzu, committen Sie die Änderungen, und pushen Sie den Branch an GitHub.

    git add azure-pipelines.yml
    git commit -m "Run load tests with Apache JMeter"
    git push origin jmeter
    

Beobachten der Testausführung in Azure Pipelines

Hier beobachten Sie, wie die Pipeline ausgeführt wird. Die Auslastungstests werden während der Stagingphase ausgeführt.

  1. Wechseln Sie in Azure Pipelines zum Build, und verfolgen Sie dessen Ausführung.

    In der Stagingphase werden die Auslastungstests nach der Bereitstellung der Website ausgeführt.

  2. Wechseln Sie nach dem Build zur Zusammenfassungsseite.

    Screenshot of Azure Pipelines, showing the completed stages.

    Sie sehen, dass die Bereitstellung und die Auslastungstests erfolgreich abgeschlossen wurden.

  3. Beachten Sie die Zusammenfassung im oberen Bereich der Seite.

    Sie sehen, dass das Buildartefakt für die Website von Space Game wie üblich veröffentlicht wurde. Beachten Sie auch den Abschnitt Tests und Coverage, in dem angezeigt wird, dass die Auslastungstests erfolgreich ausgeführt wurden.

    A screenshot of Azure Pipelines, showing the test summary.

  4. Wählen Sie die Testzusammenfassung aus, um den vollständigen Bericht anzuzeigen.

    Der Bericht zeigt, dass beide Tests erfolgreich waren.

    Screenshot of Azure Pipelines, showing the full test report.

    Wenn bei einem Test ein Fehler auftritt, werden hierfür detaillierte Ergebnisse angezeigt. Anhand dieser Ergebnisse können Sie die Ursache des Fehlers ermitteln.

    Denken Sie daran, dass die XSLT-Datei eine JUnit-Datei namens JUnit.xml generiert. Diese beiden Fragen werden von der JUnit-Datei beantwortet:

    • Beträgt die durchschnittliche Anforderungsdauer weniger als eine Sekunde?
    • Dauert die Ausführung von weniger als 10 Prozent der Anforderungen mehr als eine Sekunde?

    Der Bericht belegt, dass diese Anforderungen erfüllt sind. Ausführlichere Informationen finden Sie im Bericht unter Outcome (Ergebnis). Stellen Sie dann sicher, dass nur Passed (Erfolgreich) ausgewählt ist.

    Screenshot of Filtering passed tests in the test report.

    Sie sehen, dass die Testfälle für die durchschnittliche Antwortzeit und die maximale Antwortzeit beide erfolgreich waren.

    Screenshot of the test report, showing two successful test cases.

Hinweis

Sie verwenden den App Service-Plan B1, der über den Basic-Tarif läuft. Dieser Plan ist für Apps mit geringem Datenverkehr (z. B. Apps in einer Testumgebung) vorgesehen. Da Sie diesen Plan verwenden, ist die Leistung Ihrer Website möglicherweise schlechter als erwartet. In der Praxis würden Sie einen Plan für die Stagingumgebung auswählen, der der Produktionsumgebung besser entspricht. Die Pläne Standard und Premium sind beispielsweise für Produktionsworkloads vorgesehen. Sie laufen auf dedizierten VM-Instanzen.