연습 - Azure Pipelines에서 부하 테스트 실행

완료됨

이 섹션에서는 릴리스 파이프라인에서 만든 테스트 계획을 실행합니다. 테스트 계획은 Apache JMeter를 사용하여 부하 테스트를 실행합니다.

테스트를 실행하는 방법은 다음과 같습니다.

  • 테스트를 구현하는 Git 분기를 가져오고 체크 아웃합니다.
  • 파이프라인을 수정하여 JMeter를 설치하고, 테스트 계획을 실행하고, 결과를 JUnit으로 변환하고, 결과를 Azure Pipelines에 게시합니다.
  • 브랜치를 GitHub에 푸시하고, Azure Pipelines에서 테스트가 실행되는 것을 지켜본 다음, 결과를 검토합니다.

GitHub에서 분기 가져오기

이 섹션에서는 GitHub에서 jmeter 분기를 페치하여 해당 분기로 체크 아웃하거나 전환합니다.

이 분기에는 이전 모듈에서 작업한 Space Game 프로젝트가 포함되어 있습니다. 또한 시작할 Azure Pipelines 구성을 포함합니다.

  1. Visual Studio Code에서 통합 터미널을 엽니다.

  2. Microsoft 리포지토리에서 git checkout라는 분기를 다운로드하고 해당 분기로 전환하려면 다음 jmetergit fetch 명령을 실행합니다.

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

    업스트림은 Microsoft GitHub 리포지토리를 참조합니다. 프로젝트의 Git 구성은 Microsoft 리포지토리에서 프로젝트를 포크하고 로컬로 복제할 때 해당 관계를 설정했기 때문에 업스트림 원격을 이해합니다.

    잠시 후에 이 분기를 origin이라는 GitHub 리포지토리로 푸시합니다.

  3. 필요에 따라 Visual Studio Code에서 azure-pipelines.yml 파일을 엽니다. 초기 구성을 검토합니다.

    구성은 이 학습 경로의 이전 모듈에서 만든 구성과 유사합니다. 애플리케이션의 릴리스 구성만 빌드합니다. 간단히 하기 위해 이전 모듈에서 설정한 트리거, 수동 승인 및 테스트를 생략합니다.

    비고

    더 강력한 구성은 빌드 프로세스에 참여하는 분기를 지정할 수 있습니다. 예를 들어 코드 품질을 확인하기 위해 모든 분기에 변경 내용을 푸시할 때마다 단위 테스트를 실행할 수 있습니다. 더 철저한 테스트를 수행하는 환경에 애플리케이션을 배포할 수도 있습니다. 하지만 끌어오기 요청이 있거나, 릴리스 후보가 있거나, 코드를 ‘main’에 병합할 때만 이 배포를 실행합니다.

    자세한 내용은 Git 및 GitHub 및 빌드 파이프라인 트리거를 사용하여 빌드 파이프라인에서 코드 워크플로구현을 참조하세요.

  4. 필요에 따라 Visual Studio Code에서 JMeter 테스트 계획 파일, LoadTest.jmx 및 XLST 변환 JMeter2JUnit.xsl을 확인할 수 있습니다. XLST 파일은 Azure Pipelines가 결과를 시각화할 수 있도록 JMeter 출력을 JUnit으로 변환합니다.

Azure Pipelines에 변수 추가

팀의 원래 테스트 계획은 스테이징 환경에서 실행되는 Space Game 웹 사이트의 호스트 이름에 대해 하드 코딩된 값을 제공합니다.

테스트 계획을 보다 유연하게 만들기 위해 버전은 JMeter 속성을 사용합니다. 속성을 명령줄에서 설정할 수 있는 변수로 간주합니다.

JMeter에서 변수를 hostname 정의하는 방법은 다음과 같습니다.

Apache JMeter에서 호스트 이름 변수를 설정하는 스크린샷

hostname 변수가 변수를 읽기 위해 hostname 함수를 사용하는 방법은 다음과 같습니다.

Apache JMeter에서 호스트 이름 변수를 읽는 스크린샷

해당 테스트 계획 파일 인 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에서 실행되는 사이트의 호스트 이름을 가리킵니다. 또한 설치할 JMeter 버전을 지정하도록 설정합니다 jmeterVersion .

에이전트가 실행되면 이러한 변수가 자동으로 환경 변수로 에이전트로 내보내지므로 파이프라인 구성에서 다음과 같이 JMeter를 실행할 수 있습니다.

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

이제 파이프라인 구성을 업데이트하기 전에 파이프라인 변수를 추가해 보겠습니다. 이를 수행하려면:

  1. Azure DevOps에서 Space Game - 웹 - 비기능 테스트 프로젝트로 이동합니다.

  2. 파이프라인 아래에서 라이브러리를 선택합니다.

  3. 릴리스 변수 그룹을 선택합니다.

  4. 변수에서 + 추가를 선택합니다.

  5. 변수의 이름으로 STAGING_HOSTNAME 입력합니다. 해당 값에 대해 스테이징 환경에 해당하는 App Service 인스턴스의 URL(예: tailspin-space-game-web-staging-1234.azurewebsites.net)을 입력합니다.

    중요합니다

    값에 http:// 또는 https:// 프로토콜 접두사를 포함하지 마세요. JMeter는 테스트가 실행되면 프로토콜을 제공합니다.

  6. jmeterVersion이라는 두 번째 변수를 추가합니다. 값에 대해 5.4.3을 지정합니다.

    비고

    이 모듈을 테스트하는 데 마지막으로 사용한 JMeter 버전입니다. 최신 버전을 얻으려면 Apache JMeter 다운로드를 참조하세요.

  7. 파이프라인에 변수를 저장하려면 페이지 맨 위에 있는 저장 을 선택합니다.

    변수 그룹은 다음 이미지에 표시된 것과 유사합니다.

    변수 그룹을 보여 주는 Azure Pipelines의 스크린샷 그룹에는 5개의 변수가 포함됩니다.

파이프라인 구성 수정

이 섹션에서는 스테이징 단계에서 부하 테스트를 실행하도록 파이프라인을 수정합니다.

  1. 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 작업을 사용하여 작업이 올바른 순서로 실행되는지 확인합니다. 부하 테스트를 실행하려면 App Service에 웹 사이트를 배포해야 합니다. 이 종속성을 지정하지 않으면 단계 내의 작업이 임의의 순서로 실행되거나 병렬로 실행될 수 있습니다.
    • 첫 번째 script 작업은 JMeter를 다운로드하고 설치합니다. 파이프라인 변수는 jmeterVersion 설치할 JMeter의 버전을 지정합니다.
    • 두 번째 script 작업은 JMeter를 실행합니다. -J 인수는 파이프라인에서 hostname 변수를 읽어 JMeter의 STAGING_HOSTNAME 속성을 설정합니다.
    • 세 번째 script 작업은 XSLT 프로세서인 xsltproc를 설치하고 JMeter 출력을 JUnit으로 변환합니다.
    • 태스크는 PublishTestResults@2 결과 JUnit 보고서 (JUnit.xml)를 파이프라인에 게시합니다. Azure Pipelines는 테스트 결과를 시각화하는 데 도움이 될 수 있습니다.
  2. 통합 터미널에서 인덱스 azure-pipelines.yml 추가하고, 변경 내용을 커밋하고, 분기를 GitHub로 푸시합니다.

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

테스트를 실행하는 Azure Pipelines 보기

여기서 파이프라인 실행을 확인합니다. 스테이징 중에 부하 테스트가 실행되는 것을 볼 수 있습니다.

  1. Azure Pipelines에서 빌드로 이동하고 실행되는 빌드를 추적합니다.

    스테이징하는 동안 웹 사이트가 배포된 후 부하 테스트가 실행되는 것을 볼 수 있습니다.

  2. 빌드가 완료되면 요약 페이지로 이동합니다.

    완료된 단계를 보여 주는 Azure Pipelines의 스크린샷

    배포 및 부하 테스트가 성공적으로 완료된 것을 볼 수 있습니다.

  3. 페이지 상단 부근에서 요약을 확인합니다.

    Space Game 웹 사이트에 대한 빌드 아티팩트가 항상 그처럼 게시되는 것을 볼 수 있습니다. 테스트 및 검사 섹션도 주목하십시오. 여기서 부하 테스트가 통과했음을 확인할 수 있습니다.

    테스트 요약을 보여 주는 Azure Pipelines의 스크린샷.

  4. 테스트 요약을 선택하여 전체 보고서를 확인합니다.

    보고서는 두 테스트가 모두 통과했음을 보여 줍니다.

    전체 테스트 보고서를 보여 주는 Azure Pipelines의 스크린샷

    테스트가 실패하는 경우 오류에 대한 자세한 결과가 표시됩니다. 이러한 결과에서 오류의 원인을 조사할 수 있습니다.

    XSLT 파일은 JUnit.xmlJUnit 파일을 생성합니다. JUnit 파일은 다음 두 가지 질문에 답변합니다.

    • 평균 요청 시간이 1초 미만인가요?
    • 요청의 10% 미만이 완료하는 데 1초 이상 걸리나요?

    보고서는 이러한 요구 사항이 충족된다는 것을 증명합니다. 자세한 내용을 보려면 보고서에서 결과 화살표를 선택합니다. 그런 다음 통과만 선택되어 있는지 확인합니다.

    테스트 보고서에서 통과된 테스트를 필터링한 스크린샷

    평균 응답 시간최대 응답 시간 테스트 사례 모두 성공했음을 알 수 있습니다.

    두 가지 성공적인 테스트 사례를 보여 주는 테스트 보고서의 스크린샷.

비고

기본 계층에서 실행되는 B1 App Service 계획을 사용하고 있습니다. 이 계획은 테스트 환경의 앱과 같이 트래픽 요구 사항이 낮은 앱을 위한 것입니다. 이 계획으로 인해 웹 사이트의 성능이 예상보다 적을 수 있습니다. 실제로는 프로덕션 환경과 더욱 비슷한 스테이징 환경을 위한 계획을 선택할 것입니다. 예를 들어 표준프리미엄 플랜은 프로덕션 워크로드용입니다. 전용 가상 머신 인스턴스에서 실행됩니다.