Exercice : exécuter les tests de l’interface utilisateur localement et dans le pipeline

Effectué

Avant d’exécuter leurs tests dans le pipeline, Andy et Amita veulent vérifier que leurs nouveaux tests de l’interface utilisateur fonctionnent comme prévu. Dans cette section, vous allez continuer en exécutant les tests UI Selenium d’abord en local, puis dans le pipeline.

L’écriture de tests automatisés est un processus itératif, tout comme l’écriture d’un autre type de code. Pour vos propres applications, vous devrez probablement faire quelques essais. Reportez-vous à la documentation de référence et aux exemples de code, puis corrigez les erreurs de build.

Facultatif : installer le pilote Selenium pour Microsoft Edge

Suivez cette section si vous souhaitez voir les tests exécutés localement sur Microsoft Edge.

Le package NuGet pour Chrome et Firefox installe le pilote du logiciel dans le répertoire bin avec le code de test compilé. Pour Edge, vous devez installer le pilote manuellement. Pour ce faire :

  1. Installez Microsoft Edge.

  2. Ouvrez Edge et accédez à edge://settings/help. Notez le numéro de version. Voici un exemple :

    A screenshot of the Microsoft Edge setting page, showing the version number.

  3. Accédez à la page des Téléchargements du pilote Microsoft Edge et téléchargez le pilote correspondant au numéro de version Edge. Voici un exemple :

    A screenshot of the Downloads section of the Microsoft Edge Driver page showing the matching driver version.

  4. Extrayez le fichier .zip dans le répertoire bin/Release/net6.0, sous le répertoire Tailspin.SpaceGame.Web.UITests de votre projet. S’ils n’existent pas, créez ces répertoires.

Sur macOS, vous risquez de devoir mettre à jour votre stratégie système pour autoriser l’exécution de msedgedriver. Pour cela, dans Visual Studio Code, exécutez la commande spctl suivante à partir du terminal :

spctl --add Tailspin.SpaceGame.Web.UITests/bin/Release/net6.0/msedgedriver

Exporter des variables d’environnement

Plus tard dans ce module, vous exécuterez des tests Selenium sur Windows Server 2019. La documentation répertorie les logiciels qui sont préinstallés pour vous.

La section Pilotes web Selenium répertorie les versions de pilote Selenium qui sont disponibles pour Chrome, Firefox et Edge. Voici un exemple :

A screenshot showing the documentation for the installed Selenium drivers on the build agent.

Pour chaque pilote, vous avez la variable d’environnement qui est mappée à l’emplacement de ce pilote. Par exemple, ChromeWebDriver est mappé à l’emplacement du pilote Chrome.

Le code des tests unitaires est déjà configuré pour lire ces variables d’environnement. Ces variables indiquent à Selenium où trouver les fichiers exécutables du pilote. Pour exécuter les tests unitaires localement, vous devez exporter ces mêmes variables d’environnement.

Dans Visual Studio Code, accédez au terminal. Exécutez ensuite ces commandes. Remplacez le chemin indiqué par le chemin complet vers votre projet mslearn-tailspin-spacegame-web-deploy.

Important

Veillez à exécuter ces commandes et à définir les variables d’environnement dans la même fenêtre de terminal que celle utilisée pour exécuter les tests.

driverDir="C:\Users\user\mslearn-tailspin-spacegame-web-deploy\Tailspin.SpaceGame.Web.UITests\bin\Release\net6.0"
export ChromeWebDriver=$driverDir
export EdgeWebDriver=$driverDir
export GeckoWebDriver=$driverDir

Exécuter les tests localement

La méthode Setup dans HomePageTest.cs accède à la page d’accueil Space Game après avoir défini la variable membre driver.

Bien que vous puissiez coder en dur l’URL du site, nous lisons ici l’URL à partir d’une variable d’environnement nommée SITE_URL. Ainsi, vous pouvez exécuter les tests plusieurs fois sur différentes URL.

// Navigate to the site.
// The site name is stored in the SITE_URL environment variable to make 
// the tests more flexible.
string url = Environment.GetEnvironmentVariable("SITE_URL");
driver.Navigate().GoToUrl(url + "/");

Étant donné que vous n’avez pas encore déployé le site web Space Game dans votre environnement App Service, vous utiliserez le site hébergé par Microsoft pour exécuter les tests localement.

Pour exécuter les tests localement :

  1. Dans Visual Studio Code, accédez au terminal intégré et ouvrez une nouvelle fenêtre de terminal.

  2. Exécutez la commande suivante dans la nouvelle fenêtre de terminal.

    dotnet build --configuration Release
    dotnet run --configuration Release --no-build --project Tailspin.SpaceGame.Web
    
  3. Prenez note du lien du site web local : dans cet exemple, c’est http://localhost:5000.

  4. Revenez à la fenêtre de terminal où vous avez défini les variables d’environnement à l’étape précédente et vérifiez que vous êtes dans le répertoire racine de votre projet. Voici un exemple :

    cd ~/mslearn-tailspin-spacegame-web-deploy
    
  5. Exportez la variable d’environnement SITE_URL. Utilisez le lien avec exécution locale que vous avez obtenu à l’étape précédente.

    export SITE_URL="http://localhost:5000"
    

    Cette variable pointe vers le site web Space Game hébergé par Microsoft.

  6. Exécutez les tests de l’interface utilisateur.

    dotnet test --configuration Release Tailspin.SpaceGame.Web.UITests
    

    Ce code exécute les tests qui se trouvent dans le projet Tailspin.SpaceGame.Web.UITests.

    Pendant l’exécution des tests, un ou plusieurs navigateurs s’affichent. Selenium contrôle chaque navigateur et suit les étapes de test que vous avez définies.

    Notes

    Ne vous inquiétez pas si les trois navigateurs n’apparaissent pas. Par exemple, vous ne verrez pas les tests s’exécuter sur Chrome si Chrome n’est pas installé ou si votre version est incompatible. Même si vous ne voyez qu’un seul navigateur, vous pouvez avoir la certitude que vos tests fonctionnent. Dans la pratique, dans votre environnement de développement local, vous souhaitez peut-être configurer tous les navigateurs sur lesquels vous voulez réaliser les tests. Cette installation vous permet de vérifier que vos tests se comportent comme prévu dans chaque configuration avant d’exécuter vos tests dans le pipeline.

  7. À partir du terminal, effectuez le suivi de la sortie de chaque test. Notez également le résumé de la série de tests à la fin.

    Cet exemple montre que sur neuf tests, tous ont été couronnés de succès et aucun n'a été ignoré :

    Passed!  - Failed:     0, Passed:     9, Skipped:     0, Total:     9, Duration: 5 s 
    

Ajoutez la variable SITE_URL à Azure Pipelines

Précédemment, vous avez défini la variable d’environnement SITE_URL localement pour que vos tests soient en mesure de pointer chaque navigateur. Vous pouvez ajouter cette variable à Azure Pipelines. Le processus est similaire à l’ajout des variables pour vos instances App Service. Quand l’agent s’exécute, cette variable est automatiquement exportée vers l’agent en tant que variable d’environnement.

Nous allons maintenant ajouter la variable de pipeline avant de mettre à jour la configuration de votre pipeline. Pour ce faire :

  1. Dans Azure DevOps, accédez à votre projet Space Game - web - Functional tests.

  2. Sous Pipelines, sélectionnez Bibliothèque.

  3. Sélectionnez le groupe de variables Release.

  4. Sous Variables, sélectionnez + Ajouter.

  5. Pour le nom de votre variable, entrez SITE_URL. Comme valeur, entrez l’URL de l’instance App Service qui correspond à votre environnement de test, par exemple http://tailspin-space-game-web-test-10529.azurewebsites.net.

  6. Dans la partie supérieure de la page, sélectionnez Enregistrer pour enregistrer votre variable dans le pipeline.

    Votre groupe de variables devrait ressembler à celui-ci :

    A screenshot of Azure Pipelines, showing the variable group. The group contains four variables.

Modifier la configuration du pipeline

Dans cette section, vous modifiez la configuration du pipeline pour exécuter vos tests Selenium de l’interface utilisateur dans la phase Test.

  1. Dans Visual Studio Code, ouvrez le fichier azure-pipelines.yml. Modifiez ensuite le fichier comme suit :

    Conseil

    Ce fichier contient quelques modifications. Nous vous recommandons donc de remplacer le fichier complet par ceci.

    trigger:
    - '*'
    
    variables:
      buildConfiguration: 'Release'
      dotnetSdkVersion: '6.x'
    
    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: '$(System.DefaultWorkingDirectory)/**/Tailspin.SpaceGame.Web.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'
      - job: RunUITests
        dependsOn: Deploy
        displayName: 'Run UI tests'
        pool:
          vmImage: 'windows-2019'
        variables:
        - group: 'Release'
        steps: 
        - task: UseDotNet@2
          displayName: 'Use .NET SDK $(dotnetSdkVersion)'
          inputs:
            version: '$(dotnetSdkVersion)'
        - task: DotNetCoreCLI@2
          displayName: 'Build the project - $(buildConfiguration)'
          inputs:
            command: 'build'
            arguments: '--configuration $(buildConfiguration)'
            projects: '$(System.DefaultWorkingDirectory)/**/*UITests.csproj'
        - task: DotNetCoreCLI@2
          displayName: 'Run unit tests - $(buildConfiguration)'
          inputs:
            command: 'test'
            arguments: '--no-build --configuration $(buildConfiguration)'
            publishTestResults: true
            projects: '$(System.DefaultWorkingDirectory)/**/*UITests.csproj'
    
    - 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'
    

    Le fichier comprend ces trois modifications :

    • La variable dotnetSdkVersion est déplacée vers le haut du fichier, de sorte que des phases multiples peuvent y accéder. Ici, la phase Build et la phase Test requièrent cette version de .NET Core.

    • La phase Build publie uniquement le package du site web Space Game en tant qu’artefact de build. Précédemment, vous avez publié les artefacts comme suit :

      - 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
      

      Cette tâche génère deux artefacts de build : le package de site web Space Game et les tests de l’interface utilisateur compilés. Nous créons les tests UI pendant la phase de build pour nous assurer qu’ils seront compilés pendant la phase de test, mais nous n’avons pas besoin de publier le code de test compilé. Nous le générons de nouveau dans la phase Test lors de l’exécution des tests.

    • La phase Test comprend un deuxième travail qui génère et exécute les tests. Ce travail ressemble à celui que vous avez utilisé dans le module Exécuter des tests de qualité dans votre pipeline de build à l’aide d’Azure Pipelines. Dans ce module, vous avez exécuté des tests NUnit qui ont vérifié la fonctionnalité de filtrage du classement.

      Rappelez-vous qu’un travail de déploiement est un type de travail spécial qui joue un rôle important dans vos étapes de déploiement. Le deuxième travail est un travail normal qui exécute les tests Selenium sur un agent Windows Server 2019. Bien que nous utilisions un agent Linux pour générer l’application, nous utilisons ici un agent Windows pour exécuter les tests de l’interface utilisateur. Nous utilisons un agent Windows, car Amita exécute les tests manuels sur Windows et c’est le système d’exploitation qu’utilisent la plupart des clients.

      Le travail RunUITests dépend du travail Deploy pour s’assurer que les travaux s’exécutent dans le bon ordre. Vous allez déployer le site web sur App Service avant d’exécuter les tests de l’interface utilisateur. Si vous ne spécifiez pas cette dépendance, les travaux dans cette phase peuvent s’exécuter dans n’importe quel ordre ou en parallèle.

  2. Dans le terminal intégré, ajoutez azure-pipelines.yml à l’index, validez les modifications, puis envoyez (push) la branche vers GitHub.

    git add azure-pipelines.yml
    git commit -m "Run Selenium UI tests"
    git push origin selenium
    

Regarder Azure Pipelines exécuter les tests

Ici, vous observez l’exécution du pipeline. Le pipeline exécute les tests Selenium de l’interface utilisateur dans la phase Test.

  1. Dans Azure Pipelines, accédez au build et effectuez son suivi lors de son exécution.

    Pendant la génération, vous observez les tests automatisés qui s’exécutent après le déploiement du site web.

    A screenshot of Azure Pipelines, showing the running stages.

  2. Une fois la build terminée, accédez à la page récapitulative.

    A screenshot of Azure Pipelines, showing the completed stages.

    Vous notez que le déploiement et les tests UI se sont terminés correctement.

  3. Dans la partie supérieure de la page, notez le récapitulatif.

    Vous notez que l’artefact de build pour le site web Space Game est publié comme toujours. Notez également la section Tests et couverture qui indique que les tests Selenium ont réussi.

    A screenshot of Azure Pipelines, showing the test summary.

  4. Sélectionnez le récapitulatif des tests pour voir le rapport complet.

    Le rapport indique que les neuf tests ont réussi. Ces tests incluent trois tests sur trois navigateurs.

    A screenshot of Azure Pipelines, showing the full test report.

    En cas d’échec d’un test, vous obtenez les résultats détaillés de la défaillance. À partir de là, vous pouvez examiner la source de la défaillance, la corriger localement, puis envoyer (push) les modifications nécessaires afin que les tests s’effectuent avec succès dans le pipeline.

Amita : Cette automatisation est passionnante ! Je dispose maintenant de tests de l’interface utilisateur que je peux exécuter dans le pipeline. Les tests vont nous permettre de gagner beaucoup de temps à long terme. J’ai également un modèle à suivre pour ajouter d’autres tests. Mieux encore : les tests de l’interface utilisateur nous apportent une confiance supplémentaire quant à la qualité du code.

Andy : C’est tout à fait vrai. N’oublie pas que les tests que tu exécutes manuellement de manière répétée sont de bons candidats pour l’automatisation. Bonne chance pour ajouter plus de tests. Si tu es bloquée ou que tu as besoin d’un réviseur de code, tu sais où me trouver.