練習 - 在本機和管線中執行 UI 測試

已完成

在 Andy 和 Amita 在管線中執行其測試之前,他們想要驗證其新的 UI 測試是否做其應做的事情。 在本章節中,您會先在本機執行 Selenium UI 測試,然後在管線中執行。

撰寫自動化測試是一種反覆流程,就像撰寫任何其他類型的程式碼一樣。 針對您自己的應用程式,您可能需要嘗試一些方法、參閱參考文件和範例程式碼,以及修正組建錯誤。

選用:安裝適用 Microsoft Edge 的 Selenium 驅動程式

如果您想要在 Microsoft Edge 查看本機上執行的測試,請遵循此章節。

適用於 Chrome 和 Firefox 的 NuGet 套件會在 bin 目錄下安裝驅動程式軟體,以及編譯的測試程式碼。 若為 Edge,您需要手動安裝驅動程式。 若要這麼做︰

  1. 安裝 Microsoft Edge

  2. 開啟 Edge 並瀏覽至 edge://settings/help。 記下版本號碼。 以下是範例:

    Microsoft Edge 設定頁面的螢幕擷取畫面,其中顯示版本號碼。

  3. 瀏覽至 Microsoft Edge 驅動程式下載 頁面,並下載符合 Edge 版本號碼的驅動程式。 以下是範例:

    Microsoft Edge 驅動程式頁面的 [下載] 區段的螢幕擷取畫面,其中顯示相符的驅動程式版本。

  4. .zip 檔案解壓縮至您專案的 Tailspin.SpaceGame.Web.UITests 目錄下的 bin/Release/net6.0 目錄。 如果這些目錄不存在,請建立它們。

在 macOS 上,您可能需要更新系統原則,以允許 msedgedriver 執行。 若要這樣做,請在 Visual Studio Code 中從終端機執行下列 spctl 命令:

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

匯出環境變數

稍後在本課程模組中,您將在 Windows Server 2019 上執行 Selenium 測試。 文件會列出為您預先安裝的軟體。

Selenium Web 驅動程式一節列出 Chrome、Firefox 和 Edge 可以使用的 Selenium 驅動程式版本。 以下是範例:

顯示組建代理程式上所安裝 Selenium 驅動程式文件的螢幕擷取畫面。

針對每個驅動程式,您會擁有與該驅動程式位置對應的環境變數。 例如,ChromeWebDriver 對應至 Chrome 驅動程式的位置。

單元測試程式碼已設定為讀取這些環境變數。 這些變數會告訴 Selenium 哪裡可以找到驅動程式可執行檔。 若要在本機執行單元測試,您需要匯出這些相同的環境變數。

從 Visual Studio Code 中,移至終端機。 然後執行這些命令。 將顯示的路徑取代為 mslearn-tailspin-spacegame-web-deploy 專案的完整路徑。

重要

請務必執行這些命令,並在您用來執行測試的相同終端視窗中設定環境變數。

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

在本機執行 UI 測試

HomePageTest.cs 中的 Setup 方法會在設定 driver 成員變數之後,瀏覽至 Space Game 首頁。

雖然您可以對網站 URL 進行硬式編碼,但在這裡,我們會從名為 SITE_URL 的環境變數讀取 URL。 如此一來,您就可以針對不同的 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 + "/");

由於您尚未將 Space Game 網站部署到您的 App Service 環境,因此您將使用 Microsoft 裝載的網站,在本機執行測試。

若要在本機執行測試:

  1. 在 Visual Studio Code 中,移至整合式終端,然後開啟新的終端視窗。

  2. 在新的終端視窗中執行下列命令。

    dotnet build --configuration Release
    dotnet run --configuration Release --no-build --project Tailspin.SpaceGame.Web
    
  3. 記下本機網站連結,在此範例中為 http://localhost:5000

  4. 切換回您在上一個步驟中設定環境變數的終端視窗,並確定您位於專案的根目錄中。 以下是範例:

    cd ~/mslearn-tailspin-spacegame-web-deploy
    
  5. 匯出 SITE_URL 環境變數。 使用您在上一個步驟中取得的本機執行連結。

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

    這個變數指向 Microsoft 裝載的 Space Game 網站。

  6. 執行 UI 測試。

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

    此程式碼會執行位於 Tailspin.SpaceGame.Web.UITests 專案中的測試。

    當測試執行時,一或多個瀏覽器即會出現。 Selenium 會控制每個瀏覽器,並遵循您所定義的測試步驟。

    注意

    如果這三個瀏覽器都未出現,請不要擔心。 例如,如果您沒有安裝 Chrome 或有不相容的版本,則不會看到測試在 Chrome 上執行。 只看到一個瀏覽器將協助您確信您的測試正在運作。 實際上,在您的本機開發環境中,您可能會想要設定您想要針對其進行測試的所有瀏覽器。 此設定可讓您在管線中執行您的測試之前,先驗證您的測試在每個組態中是否如預期般運作。

  7. 從終端機中,追蹤每個測試的輸出。 另請注意結尾的測試回合摘要。

    此範例顯示在九個測試中,所有九個測試都成功,而且略過零個測試:

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

將 SITE_URL 變數新增至 Azure Pipelines

稍早,您在本機設定 SITE_URL 環境變數,讓您的測試可以知道要在何處指向每個瀏覽器。 您可以將此變數新增至 Azure Pipelines。 此流程類似於您為 App Service 執行個體新增變數的方式。 當代理程式執行時,此變數會自動匯出至代理程式做為環境變數。

現在,讓我們先新增管線變數,然後再更新您的管線組態。 若要這麼做︰

  1. 在 Azure DevOps 中,移至您的 Space Game - web - Functional tests 專案。

  2. 在 [管線] 下,選取 [程式庫]

  3. 選取 [發行] 變數群組。

  4. 在 [變數] 下,選取 [+ 新增]

  5. 針對您的變數名稱,輸入 SITE_URL。 輸入 App Service 執行個體的 URL 做為其值,此 URL 對應至您的測試環境,例如 http://tailspin-space-game-web-test-10529.azurewebsites.net

  6. 在頁面頂端附近,選取 [儲存],將您的變數儲存至管線。

    您的變數群組應如下所示:

    Azure Pipelines 的螢幕擷取畫面,其中顯示變數群組。此群組包含四個變數。

修改管線設定

在本節中,您會修改管線組態,以在「測試」階段執行您的 Selenium UI 測試。

  1. 在 Visual Studio Code 中,開啟 azure-pipelines.yml 檔案。 然後修改此檔案,如下所示:

    提示

    此檔案包含一些變更,因此建議您將整個檔案取代為您在這裡看到的內容。

    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'
    

    檔案包含這三個變更:

    • dotnetSdkVersion 變數會移至檔案頂端,讓多個階段可以對其進行存取。 在這裡,「組建」階段和「測試」階段需要這個版本的 .NET Core。

    • 「組建」階段只會發佈 Space Game 網站套件做為組建成品。 先前,您已發佈如下的成品:

      - 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
      

      此工作會產生兩個組建成品:Space Game 網站套件和已編譯的 UI 測試。 我們會在組建階段建置 UI 測試,以確保其會在測試階段編譯,但我們不需要發佈已編譯的測試程式碼。 當測試執行時,我們會在「測試」階段重新組建 UI 測試。

    • 「測試」階段包括第二個組建並執行測試的作業。 此作業類似於您在使用 Azure Pipelines 在您的組建管線中執行品質測試課程模組中所使用的作業。 在該課程模組中,您已執行驗證排行榜篩選功能的 NUnit 測試。

      回想一下,「部署作業」是一種特殊類型的作業,其在部署階段扮演重要角色。 第二個作業是在 Windows Server 2019 代理程式上執行 Selenium 測試的一般作業。 雖然我們使用 Linux 代理程式來組建應用程式,但在這裡我們會使用 Windows 代理程式來執行 UI 測試。 我們使用 Windows 代理程式,因為 Amita 會在 Windows 上執行手動測試,而且這就是大部分客戶所使用的。

      RunUITests 作業取決於 Deploy 作業,以確保這些作業以正確的順序執行。 您會在執行 UI 測試之前將網站部署至 App Service。 如果您未指定此相依性,階段內的作業可以依任何順序執行或平行執行。

  2. 在整合式終端中,將 azure-pipelines.yml 新增至索引、認可變更,然後將分支向上推送至 GitHub。

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

觀察 Azure Pipelines 執行測試

您可以在這裡監看管線執行。 管線會在「測試」階段執行 Selenium UI 測試。

  1. 在 Azure Pipelines 中,移至組建並在該組建執行時加以追蹤。

    在組建期間,您會看到自動化測試在網站部署之後執行。

    Azure Pipelines 的螢幕擷取畫面,顯示執行中階段。

  2. 建置完成後,請移至摘要頁面。

    Azure Pipelines 的螢幕擷取畫面,顯示已完成的階段。

    您會注意到部署和 UI 測試順利完成。

  3. 請注意頁面頂端附近的摘要。

    您會注意到 Space Game 網站的組建成品與往常一樣進行發佈。 亦請注意 [測試和涵蓋範圍] 區段,其中顯示 Selenium 測試已通過。

    Azure Pipelines 的螢幕擷取畫面,顯示測試摘要。

  4. 選取測試摘要來查看完整的報告。

    此報告顯示全部九個測試都已通過。 這些測試包括三個跨瀏覽器的測試。

    顯示完整測試報告的 Azure Pipelines 螢幕擷取畫面。

    如果有任何測試失敗,您會收到失敗的詳細結果。 從這裡,您可以調查失敗的來源、在本機修正該失敗,然後推送必要的變更,讓測試在管線通過。

Amita:這項自動化令人興奮! 我現在有可以在管線中執行的 UI 測試。 這些測試終究確實會節省我們的時間。 我另有一種要遵循的模式來新增更多測試。 最棒的是,UI 測試提升了我們對程式碼品質的信心。

Andy:全部都對。 請記住,您重複手動執行的測試是非常適合自動化的候選者。 祝您好運,可以新增更多測試。 如果您遇到困難或需要程式碼檢閱者,您知道可在哪裡找到我。