Ejercicio: Ejecución de pruebas de carga en Azure Pipelines

Completado

En esta sección, ejecutará el plan de pruebas que creó en la canalización de versión. El plan de pruebas usa Apache JMeter para ejecutar pruebas de carga.

Aquí se muestra cómo ejecutar las pruebas:

  • Capture y extraiga del repositorio una rama de Git que implemente las pruebas.
  • Modifique la canalización para instalar JMeter, ejecutar el plan de pruebas, transformar los resultados en JUnit y publicar los resultados en Azure Pipelines.
  • Inserte la rama en GitHub, observe la ejecución de las pruebas en Azure Pipelines y, después, examine los resultados.

Captura de la rama de GitHub

En esta sección, capturaremos la rama jmeter de GitHub y la extraeremos del repositorio, o cambiaremos a ella.

Esta rama contiene el proyecto Space Game con el que ya ha trabajado en los módulos anteriores. También contiene una configuración de Azure Pipelines con la que empezar.

  1. En Visual Studio Code, abra el terminal integrado.

  2. Ejecute los comandos git fetch y git checkout siguientes para descargar una rama denominada jmeter desde el repositorio de Microsoft y cambie a esa rama:

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

    Recuerde que upstream hace referencia al repositorio de GitHub de Microsoft. La configuración de Git del proyecto conoce el repositorio remoto upstream porque hemos configurado esa relación al bifurcar el proyecto desde el repositorio de Microsoft y clonarlo localmente.

    En resumen, va a insertar esta rama en el repositorio de GitHub, conocido como origin.

  3. Opcionalmente, en Visual Studio Code, abra el archivo azure-pipelines.yml. Revise la configuración inicial.

    La configuración es similar a las que creamos en los módulos anteriores de esta ruta de aprendizaje. Solo compila la configuración de versión de la aplicación. Por motivos de brevedad, omite los desencadenadores, las aprobaciones manuales y las pruebas que ha configurado en módulos anteriores.

    Nota:

    Una configuración más sólida podría especificar las ramas que participan en el proceso de compilación. Por ejemplo, para facilitar la comprobación de la calidad del código, podríamos ejecutar pruebas unitarias cada vez que insertemos un cambio en cualquier rama. También podríamos implementar la aplicación en un entorno que realice pruebas más exhaustivas. Pero esta implementación solo se realiza cuando se tiene una solicitud de incorporación de cambios, cuando se tiene una versión candidata para lanzamiento o cuando se combina código en la rama principal.

    Para obtener más información, vea Implementación de un flujo de trabajo de código en la canalización de compilación con Git y GitHub y Desencadenadores de canalización de compilación.

  4. Opcionalmente, en Visual Studio Code, puede extraer el archivo del plan de pruebas de JMeter, LoadTest.jmx y la transformación XLST, JMeter2JUnit.xsl. El archivo XLST transforma la salida de JMeter en JUnit para que Azure Pipelines pueda visualizar los resultados.

Adición de variables a Azure Pipelines

El plan de pruebas original del equipo proporciona un valor codificado de forma rígida para el nombre de host del sitio web Space Game que se ejecuta en el entorno de ensayo.

Para que el plan de pruebas sea más flexible, la versión usa una propiedad de JMeter. Piense en una propiedad como una variable que se puede establecer desde la línea de comandos.

Así es cómo se define la variable hostname en JMeter:

Screenshot of setting the hostname variable in Apache JMeter.

Aquí, la variable hostname usa la función __P para leer la variable hostname.

Screenshot for reading the hostname variable in Apache JMeter.

El archivo del plan de pruebas correspondiente, LoadTest.jmx, especifica esta variable y la usa para establecer el nombre de host.

Al ejecutar JMeter desde la línea de comandos, use el argumento -J para establecer la propiedad hostname. Este es un ejemplo:

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

Aquí se establece la variable STAGING_HOSTNAME en Azure Pipelines. Esta variable apunta al nombre de host del sitio que se ejecuta en App Service en el entorno de ensayo. También puede establecer jmeterVersion para especificar la versión de JMeter que se va a instalar.

Cuando se ejecuta el agente, estas variables se exportan automáticamente al agente como variables de entorno, por lo que la configuración de la canalización puede ejecutar JMeter de esta manera:

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

Vamos a agregar las variables de la canalización ahora, antes de actualizar la configuración de la canalización. Para ello:

  1. En Azure DevOps, vaya al proyecto Space Game - web - Nonfunctional tests.

  2. En Canalizaciones, seleccione Biblioteca.

  3. Seleccione el grupo de variables Release.

  4. En Variables, seleccione + Agregar.

  5. Para el nombre de la variable, escriba STAGING_HOSTNAME. Como valor, escriba la dirección URL de la instancia de App Service que corresponde al entorno de ensayo, como tailspin-space-game-web-staging-1234.azurewebsites.net.

    Importante

    No incluya el prefijo de protocolo http:// o https:// en el valor. JMeter proporciona el protocolo cuando se ejecutan las pruebas.

  6. Agregue una segunda variable denominada jmeterVersion. Como valor, especifique 5.4.3.

    Nota:

    Esta es la versión de JMeter que se utilizó por última vez para probar este módulo. Para obtener la última versión, consulte Descarga de Apache JMeter.

  7. Para guardar la variable en la canalización, seleccione Guardar cerca de la parte superior de la página.

    El grupo de variables es similar al que se muestra en la imagen siguiente:

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

Modificación de la configuración de canalización

En esta sección, modificará la canalización para ejecutar las pruebas de carga durante la fase de Ensayo.

  1. En Visual Studio Code, abra el archivo azure-pipelines.yml. A continuación, modifique el archivo de la siguiente manera:

    Sugerencia

    Puede reemplazar todo el archivo o simplemente actualizar el elemento que está resaltado.

    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
    

    A continuación se incluye un resumen de los cambios:

    • El trabajo RunLoadTests realiza pruebas de carga desde un agente Linux.
    • El trabajo RunLoadTests depende del trabajo Deploy para asegurarse de que los trabajos se ejecutan en el orden correcto. Debe implementar el sitio web en App Service antes de poder ejecutar las pruebas de carga. Si no se especifica esta dependencia, los trabajos de la fase pueden ejecutarse en cualquier orden o en paralelo.
    • La primera tarea script descarga e instala JMeter. La variable de canalización jmeterVersion especifica la versión de JMeter que se va a instalar.
    • La segunda tarea script ejecuta JMeter. El argumento -J establece la propiedad hostname en JMeter leyendo la variable STAGING_HOSTNAME de la canalización.
    • La tercera tarea script instala xsltproc, un procesador XSLT, y transforma la salida de JMeter en JUnit.
    • La tarea PublishTestResults@2 publica el informe JUnit resultante, JUnit.xml, en la canalización. Azure Pipelines puede ayudarle a visualizar los resultados de las pruebas.
  2. En el terminal integrado, agregue azure-pipelines.yml al índice, confirme los cambios e inserte la rama en GitHub.

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

Vea cómo Azure Pipelines ejecuta las pruebas

Aquí verá la ejecución de la canalización. Verá la ejecución de las pruebas de carga durante la fase de Ensayo.

  1. En Azure Pipelines, vaya a la compilación y realice el seguimiento a medida que se ejecuta.

    Durante la fase de Ensayo, ve la ejecución de las pruebas de carga una vez que se ha implementado el sitio web.

  2. Una vez que ha finalizado la compilación, vaya a la página de resumen.

    Screenshot of Azure Pipelines, showing the completed stages.

    Verá que la implementación y las pruebas de carga se han completado correctamente.

  3. Consulte el resumen en la parte superior de la página.

    Verá que el artefacto de compilación para el sitio web de Space Game está publicado como siempre. Observe también la sección Pruebas y cobertura, la cual muestra que se han superado las pruebas de carga.

    A screenshot of Azure Pipelines, showing the test summary.

  4. Seleccione el resumen de las pruebas para ver el informe completo.

    El informe muestra que se han superado ambas pruebas.

    Screenshot of Azure Pipelines, showing the full test report.

    Si se produce un error en alguna prueba, verá los resultados detallados del error. A partir de estos resultados, podría investigar el origen del error.

    Recuerde que el archivo XSLT genera un archivo JUnit denominado JUnit.xml. El archivo JUnit responde a estas dos preguntas:

    • ¿Es el tiempo de solicitud medio inferior a un segundo?
    • ¿Menos del 10 por ciento de las solicitudes tardan más de un segundo en completarse?

    El informe demuestra que se cumplen estos requisitos. Para ver más detalles, seleccione la flecha Resultado en el informe. A continuación, asegúrese de que solo está seleccionada la opción Superada.

    Screenshot of Filtering passed tests in the test report.

    Verá que se han superado ambos casos de prueba, Tiempo medio de respuesta y Tiempo de respuesta máx.

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

Nota:

Está usando el plan de App Service B1, que se ejecuta en el nivel Básico. Este plan está pensado para las aplicaciones que tienen requisitos de tráfico reducidos, como las aplicaciones de un entorno de prueba. Debido a este plan, el rendimiento de su sitio web puede ser menor de lo esperado. En la práctica, elegiría un plan para el entorno de ensayo que se ajustara más a su entorno de producción. Por ejemplo, los planes Estándar y Premium están pensados para cargas de trabajo de producción. Estos planes se ejecutan en instancias de máquina virtual dedicadas.