연습 - 코드 검사 테스트 수행

완료됨

단위 테스트에 사용하는 도구와 마찬가지로, 코드 검사에 사용하는 도구는 프로그래밍 언어와 애플리케이션 프레임워크에 따라 달라집니다.

Linux에서 실행할 .NET 애플리케이션을 대상으로 하는 경우 coverlet이 널리 사용되는 옵션입니다. Coverlet은 .NET용 플랫폼 간 코드 검사 라이브러리입니다.

.NET에서 코드 검사가 이루어지는 방식

코드 검사를 수집하는 방법은 사용 중인 프로그래밍 언어 및 프레임워크와 사용 가능한 코드 검사 도구에 따라 달라집니다.

Tailspin 시나리오에서는 다음을 확인할 수 있습니다.

  • Windows의 Visual Studio는 코드 검사를 수행하는 방법을 제공합니다.

  • Linux에서 빌드 중이므로 .NET용 플랫폼 간 코드 검사 라이브러리인 coverlet을 사용할 수 있습니다.

    단위 테스트 프로젝트에는 coverlet.msbuild NuGet 패키지가 필요합니다.

  • 코드 검사 결과는 다른 도구에서 처리될 수 있도록 XML 파일에 기록됩니다. Azure Pipelines는 CoberturaJaCoCo 검사 결과 형식을 지원합니다.

    이 모듈에서는 Cobertura를 사용하고 있습니다.

  • Cobertura 검사 결과를 사람이 읽을 수 있는 형식으로 변환하려면 ReportGenerator라는 도구를 사용할 수 있습니다.

  • ReportGenerator는 HTML을 포함한 여러 형식을 제공합니다. HTML 형식은 .NET 프로젝트의 각 클래스에 대한 상세 보고서를 만듭니다.

    특히 HtmlInline_AzurePipelines라는 HTML 형식이 있는데, 이는 Azure Pipelines와 일치하는 시각적 모양을 제공합니다.

.NET 도구를 관리하는 방법

ReportGenerator와 같은 .NET 도구는 콘솔 애플리케이션을 포함하는 특별한 NuGet 패키지입니다. .NET 도구는 전역 도구로 관리하거나 로컬 도구로 관리할 수 있습니다.

전역 도구는 중앙 위치에 설치되며 모든 디렉터리에서 호출할 수 있습니다. 한 버전의 전역 도구가 머신의 모든 디렉터리에 사용됩니다.

로컬 도구는 특정 디렉터리로 범위가 지정된 .NET 도구의 보다 격리된 복사본입니다. 범위를 사용하면 서로 다른 디렉터리에 동일한 도구의 다양한 버전을 포함할 수 있습니다.

‘매니페스트 파일’을 사용하면 지정된 디렉터리의 로컬 도구를 관리할 수 있습니다. 해당 파일은 JSON 형식이며, 일반적으로 dotnet-tools.json으로 이름이 지정됩니다. 매니페스트 파일을 사용하면 애플리케이션을 빌드하거나 실행하는 데 필요한 특정 도구 버전을 설명할 수 있습니다.

애플리케이션 원본과 함께 소스 제어에 매니페스트 파일을 포함한 경우 개발자 및 빌드 시스템은 dotnet tool restore 명령을 실행하여 매니페스트 파일에 나열된 모든 도구를 설치할 수 있습니다. 최신 버전의 로컬 도구가 필요한 경우 매니페스트 파일에서 버전을 업데이트하기만 하면 됩니다.

더 격리된 상태를 유지하기 위해 이 모듈에서는 로컬 도구를 사용하여 작업합니다. ReportGenerator 도구를 포함하는 도구 매니페스트를 만듭니다. 또한 빌드 파이프라인을 수정하여 코드 검사 결과를 사람이 읽을 수 있는 형식으로 변환하는 ReportGenerator 도구를 설치합니다.

코드 검사를 로컬로 실행

파이프라인 코드를 작성하기 전에 수동으로 프로세스를 확인할 수 있습니다.

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

  2. 다음과 같이 dotnet new 명령을 실행하여 로컬 도구 매니페스트 파일을 만듭니다.

    dotnet new tool-manifest
    

    해당 명령은 .config/dotnet-tools.json이라는 파일을 만듭니다.

  3. 다음과 같이 dotnet tool install 명령을 실행하여 ReportGenerator를 설치합니다.

    dotnet tool install dotnet-reportgenerator-globaltool
    

    해당 명령은 최신 버전의 ReportGenerator를 설치하고 도구 매니페스트 파일에 항목을 추가합니다.

  4. 다음과 같이 dotnet add package 명령을 실행하여 coverlet.msbuild 패키지를 Tailspin.SpaceGame.Web.Tests 프로젝트에 추가합니다.

    dotnet add Tailspin.SpaceGame.Web.Tests package coverlet.msbuild
    
  5. 다음과 같이 dotnet test 명령을 실행하여 단위 테스트를 실행하고 코드 검사를 수집합니다.

    참고 항목

    Visual Studio에서 PowerShell 터미널을 사용하는 경우 줄 연속 문자는 백틱(`)이므로 여러 줄 명령에 백슬래시 문자(\) 대신 해당 문자를 사용합니다.

    dotnet test --no-build \
      --configuration Release \
      /p:CollectCoverage=true \
      /p:CoverletOutputFormat=cobertura \
      /p:CoverletOutput=./TestResults/Coverage/
    

    명령이 실패하면 다음과 같은 실행을 시도합니다.

    MSYS2_ARG_CONV_EXCL="*" dotnet test --no-build \
      --configuration Release \
      /p:CollectCoverage=true \
      /p:CoverletOutputFormat=cobertura \
      /p:CoverletOutput=./TestResults/Coverage/
    

    이 명령은 이전에 실행한 명령과 유사합니다. /p: 플래그는 coverlet에 사용할 코드 검사 형식과 결과를 배치할 위치를 알려줍니다.

  6. 다음과 같이 dotnet tool run 명령을 실행해 ReportGenerator를 사용하여 Cobertura 파일을 HTML로 변환합니다.

    dotnet tool run reportgenerator \
      -reports:./Tailspin.SpaceGame.Web.Tests/TestResults/Coverage/coverage.cobertura.xml \
      -targetdir:./CodeCoverage \
      -reporttypes:HtmlInline_AzurePipelines
    

    대부분의 HTML 파일이 프로젝트의 루트에 있는 CodeCoverage 폴더에 표시됩니다.

  7. Visual Studio Code에서 CodeCoverage 폴더를 확장하고 index.htm을 마우스 오른쪽 단추로 클릭한 다음 파일 탐색기에서 표시(macOS의 경우 Finder에서 표시 또는 Linux의 경우 상위 폴더 열기)를 선택합니다.

  8. Windows 탐색기(macOS의 경우 Finder)에서 index.htm을 두 번 클릭하여 웹 브라우저에서 엽니다.

    검사 보고서 요약이 표시됩니다.

    A screenshot of the local code coverage report summary showing 7.7 percent line coverage.

  9. 페이지 하단으로 스크롤하여 클래스 유형별 검사 분석 결과를 확인합니다.

    A screenshot of local coverage report class summary showing coverage stats across classes found in the Tailspin.SpaceGame.Web code.

  10. TailSpin.SpaceGame.Web.LocalDocumentDBRepository<T> 링크를 선택하여 추가 세부 정보를 확인합니다.

    GetItemsAsync 메서드에는 단위 테스트가 적용되지만 CountItemsAsync 메서드에는 검사가 없습니다.

    A screenshot of local class coverage detail with a visual representation of unit test coverage for two C# methods, one with all code lines green (covered) and one with all lines red (not covered).

    이는 FetchOnlyRequestedGameRegion 테스트 메서드가 GetItemsAsync 메서드를 호출하지만 CountItemsAsync 메서드를 호출하지 않기 때문에 적절합니다. (테스트 코드를 검토하려면 DocumentDBRepository_GetItemsAsyncShould.cs 파일을 참조하세요.)

분기 만들기

이제 로컬에서 코드 검사 보고서를 빌드할 수 있으므로 동일한 작업을 수행하는 빌드 파이프라인에 작업을 추가할 준비가 되었습니다.

이 섹션에서는 unit-tests 분기를 기반으로 code-coverage(이)라는 분기를 만들어 작업을 저장합니다. 실제로 해당 분기는 일반적으로 main 분기에서 만듭니다.

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

  2. 터미널에서 다음과 같이 git checkout 명령을 실행하여 code-coverage라는 분기를 만듭니다.

    git checkout -B code-coverage
    

빌드 작업 추가

이 섹션에서는 코드 검사를 측정하는 작업을 빌드 파이프라인에 추가합니다.

  1. Visual Studio Code에서 azure-pipelines.yml을 다음과 같이 수정합니다.

    trigger:
    - '*'
    
    pool:
      vmImage: 'ubuntu-20.04'
      demands:
      - npm
    
    variables:
      buildConfiguration: 'Release'
      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: 'Install .NET tools from local manifest'
      inputs:
        command: custom
        custom: tool
        arguments: 'restore'
    
    - task: DotNetCoreCLI@2
      displayName: 'Run unit tests - $(buildConfiguration)'
      inputs:
        command: 'test'
        arguments: '--no-build --configuration $(buildConfiguration) /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura /p:CoverletOutput=$(Build.SourcesDirectory)/TestResults/Coverage/'
        publishTestResults: true
        projects: '**/*.Tests.csproj'
    
    - task: DotNetCoreCLI@2
      displayName: 'Create code coverage report'
      inputs:
        command: custom
        custom: tool
        arguments: 'run reportgenerator -reports:$(Build.SourcesDirectory)/**/coverage.cobertura.xml -targetdir:$(Build.SourcesDirectory)/CodeCoverage -reporttypes:HtmlInline_AzurePipelines'
    
    - task: PublishCodeCoverageResults@1
      displayName: 'Publish code coverage report'
      inputs:
        codeCoverageTool: 'cobertura'
        summaryFileLocation: '$(Build.SourcesDirectory)/**/coverage.cobertura.xml'
    
    - 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
    
    - task: PublishBuildArtifacts@1
      displayName: 'Publish Artifact: drop'
      condition: succeeded()
    

    이 버전은 기존 구성을 기반으로 합니다. 다음은 새로운 사항에 대한 요약입니다.

    Azure Pipelines 작업 표시 이름 Description
    DotNetCoreCLI@2 로컬 매니페스트에서 .NET 도구 설치 매니페스트 파일인 dotnet-tools.json에 나열된 도구 설치
    DotNetCoreCLI@2 단위 테스트 실행 - $(buildConfiguration) 단위 테스트 실행 및 Cobertura 형식의 코드 검사 수집
    DotNetCoreCLI@2 코드 검사 보고서 만들기 Cobertura 출력을 HTML로 변환
    PublishCodeCoverageResults@1 코드 검사 보고서 게시 파이프라인에 보고서 게시

변경 내용 커밋 및 GitHub로 분기 푸시

여기서는 변경 내용을 GitHub로 푸시하고 파이프라인 실행을 확인합니다. 다시 말하지만, 현재 code-coverage 분기에 있습니다.

필수는 아니지만, 여기에서 각 파일을 개별적으로 추가하고 커밋하여 각 변경 내용을 설명적 커밋 메시지와 연결합니다.

  1. Visual Studio Code에서 터미널로 이동합니다.

  2. 다음과 같이 현재 coverlet.msbuild 패키지에 대한 참조를 포함하는 Tailspin.SpaceGame.Web.Tests.csproj 파일을 추가하고 커밋합니다.

    git add Tailspin.SpaceGame.Web.Tests/Tailspin.SpaceGame.Web.Tests.csproj
    git commit -m "Add coverlet.msbuild package"
    
  3. 다음과 같이 도구 매니페스트 파일인 dotnet-tools.json을 추가하고 커밋합니다.

    git add .config/dotnet-tools.json
    git commit -m "Add code coverage"
    
  4. 다음과 같이 업데이트된 빌드 구성이 포함된 azure-pipelines.yml을 추가하고 커밋합니다.

    git add azure-pipelines.yml
    git commit -m "Add code coverage"
    
  5. GitHub로 code-coverage 분기를 푸시합니다.

    git push origin code-coverage
    

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

여기서는 테스트가 파이프라인에서 실행되는 것을 확인한 다음, Azure Test Plans에서 결과를 시각화합니다.

  1. Azure Pipelines에서 각 단계를 통해 빌드를 추적합니다.

  2. 빌드가 완료되면 요약 페이지로 돌아가서 Code Coverage 탭을 선택합니다.

    로컬에서 테스트를 실행했을 때와 동일한 결과가 표시됩니다.

    A screenshot of Azure Pipelines showing the Code Coverage tab, with code coverage report summary showing 7.7 percent line coverage.

    선택적 단계로, Azure Pipelines에서 결과를 탐색할 수 있습니다.

대시보드 위젯 추가

이전 섹션에서는 다른 사람들이 시간 경과에 따른 테스트 결과 추세를 빠르게 검토할 수 있도록 대시보드에 Test Results Trend 위젯을 추가했습니다.

여기서는 코드 검사를 요약하는 두 번째 위젯을 추가합니다.

  1. 새 브라우저 탭에서marketplace.visualstudio.com으로 이동합니다.

  2. Azure DevOps 탭에서 code coverage를 검색합니다.

  3. Code Coverage Widgets(Shane Davis에서 게시함)를 선택합니다.

  4. Get it free를 선택합니다.

  5. 드롭다운 목록에서 Azure DevOps 조직을 선택합니다.

  6. 설치를 선택합니다.

  7. Azure DevOps로 돌아갑니다.

  8. Overview>Dashboards로 이동합니다.

  9. 편집을 선택합니다.

  10. Code Coverage를 검색한 다음 Code Coverage를 선택합니다.

    A screenshot of Visual Studio Marketplace showing the Code Coverage widget card.

  11. 코드 검사를 캔버스로 끕니다.

  12. 톱니 모양 아이콘을 선택하여 위젯을 구성합니다.

  13. 다음을 제외한 모든 기본 설정을 유지합니다.

    • 너비: 2를 입력합니다.
    • 빌드 정의: 파이프라인을 선택합니다.
    • 검사 측정: 선택
  14. 저장을 선택합니다.

  15. Done Editing을 선택합니다.

    위젯에 단위 테스트가 적용된 코드의 백분율이 표시됩니다.

    A screenshot of Azure DevOps Code Coverage widget showing 8 percent coverage of the sample project.

이제 파이프라인에 코드 검사가 설정되었습니다. 기존 코드 검사가 낮아도 시간이 지남에 따라 개선할 수 있는 기준선이 있습니다.

나중에 테스트가 검사의 최소 임계값을 제공하는지 여부를 확인하도록 coverlet을 구성할 수 있습니다. 요구 사항에 따라 임계값은 30%, 50% 또는 80%가 적용될 수 있습니다. 테스트에서 이 양보다 적은 양을 포함하면 빌드가 실패합니다.

코드 검사 파일 제거

앞서 Reportgenerator를 실행했을 때 대부분의 HTML 파일이 프로젝트의 루트에 있는 CodeCoverage 폴더에 표시되었습니다.

해당 HTML 파일은 소스 제어에 포함되지 않으므로 더 이상 필요하지 않습니다. 프로젝트의 .gitignore 파일이 CodeCoverage 디렉터리의 모든 항목을 무시하도록 이미 설정되어 있지만, 향후 모듈에서 Git 리포지토리에 추가되지 않도록 해당 파일을 삭제하는 것이 좋습니다.

Visual Studio Code에서 터미널 창으로 이동한 다음 프로젝트의 루트 디렉터리에서 다음 명령을 실행합니다.

rm -rf CodeCoverage/