演習 - Azure Pipelines でロード テストを実行する
このセクションでは、リリース パイプラインに作成したテスト計画を実行します。 テスト計画では、Apache JMeter を使用してロード テストを実行します。
テストの実行方法を次に示します。
- テストを実装する Git ブランチをフェッチしてチェックアウトします。
- JMeter をインストールし、テスト計画を実行し、結果を JUnit に変換し、結果を Azure Pipelines に発行するようにパイプラインを変更します。
- ブランチを GitHub にプッシュし、Azure Pipelines で実行されているテストを監視し、結果を確認します。
GitHub からブランチをフェッチする
このセクションでは、GitHub から jmeter
ブランチをフェッチし、そのブランチをチェックアウトします (つまりそのブランチに切り替えます)。
このブランチには、前のモジュールで作業した Space Game プロジェクトが含まれています。 また、最初に使用する Azure Pipelines 構成も含まれています。
Visual Studio Code で、統合ターミナルを開きます。
Microsoft のリポジトリから
jmeter
という名前のブランチをダウンロードし、そのブランチに切り替えるために、次のgit fetch
およびgit checkout
コマンドを実行します。git fetch upstream jmeter git checkout -B jmeter upstream/jmeter
upstream とは Microsoft GitHub リポジトリを指していることを思い出してください。 Microsoft のリポジトリからプロジェクトをフォークしてローカルにクローンしたときにアップストリーム リモートの関係をセットアップしたので、プロジェクトの Git 構成ではそれが認識されます。
すぐに、
origin
と呼ばれる独自の GitHub リポジトリにこのブランチをプッシュします。必要に応じて、Visual Studio Code で、azure-pipelines.yml ファイルを開きます。 その初期構成を確認します。
この構成は、このラーニング パスの前のモジュールで作成したものに似ています。 これによって、アプリケーションのリリース構成のみがビルドされます。 簡潔さのために、以前のモジュールで設定したトリガー、手動の承認、テストは省略されています。
Note
より堅牢な構成では、ビルド プロセスに参加するブランチを指定できます。 たとえば、コードの品質を検証するために、いずれかのブランチに変更をプッシュするたびに、単体テストを実行できます。 さらに包括的なテストを実行する環境にアプリケーションをデプロイすることもできます。 ただし、このデプロイは、pull request がある場合、リリース候補がある場合、またはコードを main にマージする場合にのみ実行します。
詳細については、Git と GitHub を使用したビルド パイプラインでのコード ワークフローの実装に関するモジュール、およびビルド パイプラインのトリガーに関するページを参照してください。
必要に応じて、Visual Studio Code で、JMeter テスト計画ファイル LoadTest、および XLST 変換 JMeter2JUnit.xsl をチェックアウトできます。 XLST ファイルは、Azure Pipelines で結果を視覚化できるように、JMeter 出力を JUnit に変換します。
変数を Azure Pipelines に追加する
チームの元のテスト計画では、ステージング環境で実行される Space Game Web サイトのホスト名にハードコーディングされた値が提供されています。
テスト計画の柔軟性を高めるために、こちらのバージョンでは JMeter プロパティを使用しています。 プロパティは、コマンド ラインから設定できる変数と考えてください。
JMeter で hostname
変数が定義される方法を次に示します。
hostname
変数が __P 関数を使用して hostname
変数を読み取る方法を次に示します。
対応するテスト計画ファイル LoadTest.jmx でこの変数が指定されており、それを使ってホスト名を設定します。
コマンド ラインから JMeter を実行する場合は、-J
引数を使用して hostname
プロパティを設定します。 次に例を示します。
apache-jmeter-5.4.3/bin/./jmeter -n -t LoadTest.jmx -o Results.xml -Jhostname=tailspin-space-game-web-staging-1234.azurewebsites.net
ここでは、Azure Pipelines に STAGING_HOSTNAME
変数を設定します。 この変数は、ステージング環境内の App Service で実行されているサイトのホスト名を指します。 また、jmeterVersion
を設定して、インストールする JMeter のバージョンを指定します。
エージェントを実行すると、これらの変数は環境変数としてエージェントに自動的にエクスポートされます。そのため、パイプラインの構成では、次のように JMeter を実行できます。
apache-jmeter-5.4.3/bin/./jmeter -n -t LoadTest.jmx -o Results.xml -Jhostname=$(STAGING_HOSTNAME)
パイプラインの構成を更新する前に、ここでパイプラインの変数を追加しましょう。 そのためには次を行います。
Azure DevOps で、Space Game - web - Nonfunctional tests プロジェクトにアクセスします。
[パイプライン] で [ライブラリ] を選択します。
[Release] 変数グループを選択します。
[Variables] で、[+ Add] を選択します。
変数の名前として「STAGING_HOSTNAME」と入力します。 値として、ステージング環境に対応する App Service インスタンスの URL (tailspin-space-game-web-staging-1234.azurewebsites.net など) を入力します。
重要
値には
http://
またはhttps://
プロトコル プレフィックスを含めないでください。 テストの実行時に、JMeter によってプロトコルが提供されます。jmeterVersion という名前の 2 つ目の変数を追加します。 その値として、5.4.3 を指定します。
Note
これは、このモジュールをテストするために最後に使用した JMeter のバージョンです。 最新バージョンを入手するには、Apache JMeter のダウンロードに関するページを参照してください。
ページの上部付近で、変数をパイプラインに保存するために、[Save] を選びます。
変数グループは、次の図で示されているようになります。
パイプライン構成を変更する
このセクションでは、"ステージング" 段階中にロード テストを実行するようにパイプラインを変更します。
Visual Studio Code で、azure-pipelines.yml ファイルを開きます。 次に、以下のようにファイルを変更します。
ヒント
ファイル全体を置き換えることも、強調表示されている部分のみを更新することもできます。
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
変更の概要を次に示します。
RunLoadTests
ジョブは、Linux エージェントからロード テストを行います。RunLoadTests
ジョブはDeploy
ジョブに依存して、ジョブが正しい順序で実行されるようにします。 ロード テストを実行する前に、Web サイトを App Service にデプロイする必要があります。 この依存関係を指定しない場合は、ステージ内のジョブを任意の順序で実行することも、並列で実行することもできます。- 最初の
script
タスクは、JMeter をダウンロードしてインストールします。jmeterVersion
パイプライン変数では、インストールする JMeter のバージョンを指定します。 - 2 番目の
script
タスクは、JMeter を実行します。-J
引数は、パイプラインからSTAGING_HOSTNAME
変数を読み取って、JMeter 内のhostname
プロパティを設定します。 - 3 番目の
script
タスクは、XSLT プロセッサである xsltproc をインストールし、JMeter 出力を JUnit に変換します。 PublishTestResults@2
タスクは、結果として生成された JUnit レポートである JUnit.xml をパイプラインに発行します。 Azure Pipelines は、テスト結果を視覚化するのに役立ちます。
統合ターミナルで、azure-pipelines.yml をインデックスに追加し、変更をコミットして、GitHub にブランチをプッシュします。
git add azure-pipelines.yml git commit -m "Run load tests with Apache JMeter" git push origin jmeter
Azure Pipelines でのテストの実行を監視する
ここでは、パイプラインの実行を監視します。 ロード テストが "ステージング" 中に実行されていることがわかります。
Azure Pipelines で、ビルドに移動し、実行中にそれをトレースします。
"ステージング" 中、Web サイトのデプロイ後にロード・テストが実行されていることがわかります。
ビルドが完了したら、概要ページに移動します。
デプロイとロード テストが正常に完了したことがわかります。
ページの上部近くにある概要を確認します。
Space Game Web サイトのビルド成果物が、いつものように発行されていることがわかります。 また、ロード テストが成功したことを示している [テストとカバレッジ] セクションにも注意してください。
テストの概要を選択して、完全なレポートを表示します。
レポートには、両方のテストが成功したことが示されています。
テストが失敗した場合は、エラーの詳細な結果が表示されます。 これらの結果から、エラーの原因を調査できます。
XSLT ファイルによって JUnit.xml という JUnit ファイルが生成されることを思い出してください。 JUnit ファイルでは、次の 2 つの質問に回答します。
- 平均要求時間は 1 秒未満か。
- 完了までにかかる時間が 1 秒を超えるのは、要求の 10% 未満か。
このレポートでは、これらの要件が満たされていることが証明されます。 詳細を表示するには、レポートにある [Outcome](結果) の矢印を選択します。 次に、[Passed](合格) のみが選択されていることを確認します。
[平均応答時間] と [最大応答時間] テスト ケースが両方とも成功だったことがわかります。
Note
Basic レベルで実行される B1 App Service プランを使用しています。 このプランは、テスト環境のアプリなど、トラフィック要件が低いアプリを対象としています。 このプランのため、Web サイトのパフォーマンスは予想よりも低くなる可能性があります。 実際には、運用環境により近いステージング環境用の計画を選びます。 たとえば、Standard および Premium プランは、運用環境のワークロードに適しています。 これらは、専用の仮想マシン インスタンスで実行されます。