Code Coverage 설정

이 제품은 선택한 Datadog 사이트에서 지원되지 않습니다. ().

Code Coverage 설정에는 다음 단계가 포함됩니다.

  1. Datadog UI에서 소스 코드 공급자와의 통합을 구성합니다.
  2. Datadog에서 코드 커버리지 데이터 액세스 권한을 구성합니다.
  3. 필요시 PR Gate를 구성하여 커버리지 임계값을 기준으로 풀 요청을 차단합니다.
  4. CI 파이프라인을 업데이트하여 코드 커버리지 보고서를 Datadog에 업로드합니다.

소스 코드 공급자와의 통합

Code Coverage는 다음을 지원합니다.

GitHub 리포지토리를 Datadog에 연결하는 방법은 GitHub 통합 설명서의 지침을 따르세요.

Code Coverage에는 다음 GitHub 앱 권한이 필요합니다.

권한액세스 수준목적
콘텐츠읽기상세 커버리지 UI에 소스 코드를 표시합니다.
풀 요청쓰기커버리지 UI에 PR 데이터를 표시하고 PR 코멘트를 작성합니다.
검사쓰기커버리지 PR Gate를 생성합니다.

다음 웹훅이 필요합니다.

웹훅목적
풀 요청PR 데이터 업데이트를 수신합니다.
풀 요청 검토PR 데이터 업데이트를 수신합니다.
풀 요청 검토 코멘트PR 데이터 업데이트를 수신합니다.
푸시Git 커밋 메타데이터를 수신합니다.

모든 항목이 올바르게 구성되면 Datadog의 GitHub 통합 페이지에 녹색 확인 표시가 나타납니다.

GitHub 앱 통합 성공 검사
Datadog 관리형 Marketplace 앱 또는 기본 설정이 적용된 사용자 지정 앱을 사용하는 경우, 필수 권한과 웹훅이 포함되어 있습니다.

GitLab 리포지토리를 Datadog에 연결하는 방법은 GitLab 소스 코드 통합 설명서의 지침을 따르세요.

자세한 내용은 Datadog 소스 통합 가이드를 참조하세요.

Azure DevOps 소스 코드 통합을 사용하여 Azure DevOps 리포지토리를 Datadog에 연결하는 방법은 Datadog 소스 코드 통합 가이드의 지침을 따르세요.

소스 코드 공급자로부터 수집되는 데이터에 대한 자세한 내용은 수집되는 데이터를 참조하세요.

데이터 액세스 권한

Datadog 관리형 역할 대신 사용자 지정 역할을 사용하는 경우, 코드 커버리지 데이터를 조회해야 하는 역할에 대해 Code Coverage Read 권한을 활성화해야 합니다.

역할 설정으로 이동하여 필요한 역할에 대해 Edit을 클릭하고, 해당 역할에 Code Coverage Read 권한을 추가한 다음 변경 사항을 저장합니다.

더 세밀한 제어를 원하면 Data Access Control을 사용하여 조직 전체가 아닌 리포지토리별로 코드 커버리지 데이터를 제한하세요. 이렇게 하면 소스 경로 및 테스트 이름과 같은 커버리지 보고서의 민감한 정보가 팀 경계를 넘어가는 것을 방지할 수 있습니다.

Datadog에서 Organization Settings > Data Access Control로 이동하여 Software Delivery 및 제한하려는 리포지토리로 범위가 지정된 Restricted Dataset를 생성합니다. 해당 데이터를 확인해야 하는 역할이나 팀에 액세스 권한을 부여합니다.

PR Gate

PR 커버리지에 대해 게이트를 설정하려면 다음 두 가지 방법 중 하나로 PR Gate 규칙을 구성할 수 있습니다.

  • Datadog UI: PR Gate 규칙 생성으로 이동하여 전체 또는 패치 커버리지에 대해 게이트를 설정하는 규칙을 구성합니다.
  • YAML 구성 파일: code-coverage.datadog.yml 파일에 게이트를 정의합니다. 이를 통해 리포지토리와 함께 코드로 게이트를 관리할 수 있습니다.

풀 요청이 열리거나 업데이트될 때 두 소스의 규칙이 모두 평가됩니다. YAML 게이트 구문 및 예시는 구성을 참조하세요.

코드 커버리지 보고서 업로드

지원되는 Test Optimization 라이브러리를 사용하여 자동으로 또는 CI 환경에서 datadog-ci CLI를 실행하여 수동으로 코드 커버리지 보고서 파일을 Datadog에 업로드합니다.

코드 커버리지 보고서 업로드 중 수집되는 데이터에 대한 자세한 내용은 수집되는 데이터를 참조하세요.

Test Optimization으로 보고서 자동 업로드

지원되는 라이브러리 및 버전

자동 코드 커버리지 보고서 업로드는 다음 Test Optimization 라이브러리 버전에서 지원됩니다.

라이브러리최초 지원 버전커버리지 소스
Ruby datadog-ci1.27.0SimpleCov
JavaScript dd-trace 5.x5.85.0Jest, Vitest 또는 NYC 커버리지
JavaScript dd-trace 6.x6.0.0Jest, Vitest 또는 NYC 커버리지
Python ddtrace4.4.0coverage.py
Java dd-java-agent1.53.0JaCoCo

이러한 버전 요구 사항은 Test Optimization 라이브러리에 의한 자동 업로드에만 적용됩니다.

자동 업로드 활성화

Code Coverage 설정은 조직, 리포지토리 또는 테스트 서비스 수준에서 적용할 수 있습니다.

  1. 라이브러리에 대한 Test Optimization 설정을 완료합니다.

  2. 지원되는 라이브러리 버전으로 업그레이드합니다.

  3. CI/CD Optimization settings에서 Code Coverage를 켭니다.

    조직 수준의 CI/CD Optimization 설정에 있는 Code Coverage 토글.
  4. 지원되는 라이브러리 및 버전에 나열된 소스에서 커버리지 보고서를 생성하는 테스트 명령을 실행합니다.

명령이 완료되면 라이브러리가 Datadog으로 보고서를 업로드합니다.

라이브러리에서 업로드한 보고서를 구성하고 필터링하려면 DD_CODE_COVERAGE_FLAGS를 지원하는 라이브러리 및 버전이 나열된 자동으로 업로드된 보고서에 플래그 추가를 참조하세요.

지원되는 커버리지 보고서 형식

Datadog은 다음과 같은 커버리지 데이터 형식을 지원합니다. 예시를 보려면 확장하세요.

TN:
SF:src/example.c
FN:3,add
FNDA:5,add
FNF:1
FNH:1
DA:3,5
DA:4,5
DA:5,5
DA:8,0
DA:9,0
LF:5
LH:3
BRDA:4,0,0,5
BRDA:4,0,1,0
BRF:2
BRH:1
end_of_record
mode: atomic
example/calculator.go:51.148,53.2 1 0
example/calculator.go:55.190,61.15 3 0
example/calculator.go:61.15,64.3 2 0
example/calculator.go:66.2,67.16 2 0
example/calculator.go:67.16,69.3 1 0
example/clients/api_client.go:27.87,31.2 3 2
example/clients/api_client.go:34.85,36.2 1 3
example/clients/api_client.go:39.126,44.2 4 3
example/clients/api_client.go:47.106,50.2 2 3
example/notifications/notifier.go:49.79,51.2 1 3
example/notifications/notifier.go:60.33,69.2 1 0
example/notifications/notifier.go:79.131,86.15 3 2
example/notifications/notifier.go:104.3,104.10 1 3
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE coverage SYSTEM "http://cobertura.sourceforge.net/xml/coverage-04.dtd">
<coverage lines-valid="5" lines-covered="3" line-rate="0.6" branches-valid="2" branches-covered="1" branch-rate="0.5" timestamp="1690658886" version="1.9">
  <sources>
    <source>src</source>
  </sources>
  <packages>
    <package name="example" line-rate="0.6" branch-rate="0.5">
      <classes>
        <class name="Example" filename="example/Example.java" line-rate="0.6" branch-rate="0.5">
          <methods>
            <method name="add" signature="(II)I" line-rate="1.0" branch-rate="1.0">
              <lines>
                <line number="3" hits="5"/>
                <line number="4" hits="5" branch="true" condition-coverage="50% (1/2)"/>
                <line number="5" hits="5"/>
              </lines>
            </method>
          </methods>
          <lines>
            <line number="3" hits="5"/>
            <line number="4" hits="5" branch="true" condition-coverage="50% (1/2)"/>
            <line number="5" hits="5"/>
            <line number="8" hits="0"/>
            <line number="9" hits="0"/>
          </lines>
        </class>
      </classes>
    </package>
  </packages>
</coverage>
<?xml version="1.0" encoding="UTF-8"?>
<report name="Example">
  <sessioninfo id="SessionId" start="1690658886000" dump="1690658887000"/>
  <package name="example">
    <sourcefile name="Example.java">
      <line nr="3" mi="0" ci="5"/>
      <line nr="4" mi="0" ci="5" mb="1" cb="1"/>
      <line nr="5" mi="0" ci="5"/>
      <line nr="8" mi="1" ci="0"/>
      <line nr="9" mi="1" ci="0"/>
    </sourcefile>
  </package>
</report>
<coverage generated="1661852015">
    <project timestamp="1661852015">
        <file name="/var/www/html/src/App/Console/CronjobRunnerCommand.php">
            <class name="App\Console\CronjobRunnerCommand" namespace="global">
                <metrics complexity="3" methods="3" coveredmethods="0" conditionals="0" coveredconditionals="0" statements="4" coveredstatements="0" elements="7" coveredelements="0"/>
            </class>
            <line num="18" type="method" name="__construct" visibility="public" complexity="1" crap="2" count="0"/>
            <line num="20" type="stmt" count="1"/>
            <line num="27" type="stmt" count="0"/>
            <line num="30" type="method" name="execute" visibility="protected" complexity="1" crap="2" count="0"/>
            <line num="32" type="stmt" count="0"/>
            <metrics loc="35" ncloc="35" classes="1" methods="3" coveredmethods="0" conditionals="0" coveredconditionals="0" statements="4" coveredstatements="0" elements="7" coveredelements="0"/>
        </file>
        <file name="/var/www/html/src/App/Console/CronjobRunnerCommand2.php">
            <line num="42" type="stmt" count="1"/>
        </file>
    </project>
</coverage>
<?xml version="1.0" encoding="utf-8"?>
<CoverageSession xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Modules>
    <Module hash="ABC123">
      <ModulePath>Example.dll</ModulePath>
      <Files>
        <File uid="1" fullPath="src\example\Example.cs" />
      </Files>
      <Classes>
        <Class>
          <Methods>
            <Method visited="true" cyclomaticComplexity="1" sequenceCoverage="100">
              <FileRef uid="1"/>
              <SequencePoints>
                <SequencePoint vc="5" sl="3" />
                <SequencePoint vc="5" sl="4" />
                <SequencePoint vc="5" sl="5" />
                <SequencePoint vc="0" sl="9" />
              </SequencePoints>
              <BranchPoints>
                <BranchPoint vc="5" sl="4" path="0"/>
                <BranchPoint vc="0" sl="4" path="1"/>
              </BranchPoints>
            </Method>
          </Methods>
        </Class>
      </Classes>
    </Module>
  </Modules>
</CoverageSession>
{
  "meta": {
    "simplecov_version": "0.21.2"
  },
  "coverage": {
    "/path/to/file1.rb": {
      "lines": [
        null,
        1,
        2,
        0,
        null,
        1,
        null,
        null,
        null,
        "ignored",
        "ignored",
        "ignored",
        null
      ],
      "branches": []
    },
    "/path/to/file2.rb": {
      "lines": [1, 1, null, 0, 1],
      "branches": []
    }
  }
}

datadog-ci CLI 설치

GitHub Actions를 사용하는 경우 이 설치 단계를 건너뛸 수 있습니다. 아래의 GitHub Actions 업로드 방법은 datadog-ci 설치를 자동으로 처리하는 전용 액션을 사용합니다.

독립형 바이너리는 Datadog CI 릴리스에서 제공됩니다. linux-x64, linux-arm64, darwin-x64, darwin-arm64(macOS) 및 win-x64(Windows) 아키텍처가 지원됩니다. 설치하려면 터미널에서 다음을 실행하세요.

curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_linux-x64" --output "/usr/local/bin/datadog-ci" && chmod +x /usr/local/bin/datadog-ci

그런 다음 datadog-ci를 사용하여 명령을 실행하세요.

datadog-ci version
curl -L --fail "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_darwin-x64" --output "/usr/local/bin/datadog-ci" && chmod +x /usr/local/bin/datadog-ci

그런 다음 datadog-ci를 사용하여 명령을 실행하세요.

datadog-ci version
Invoke-WebRequest -Uri "https://github.com/DataDog/datadog-ci/releases/latest/download/datadog-ci_win-x64" -OutFile "datadog-ci.exe"

그런 다음 Start-Process -FilePath "datadog-ci.exe"를 사용하여 명령을 실행하세요.

Start-Process -FilePath "./datadog-ci.exe" -ArgumentList version

npm

또는 CI 환경에서 Node.js를 사용할 수 있는 경우 npm을 사용하여 datadog-ci CLI를 전역으로 설치하세요.

npm install -g @datadog/datadog-ci

Docker 이미지

또는 Datadog CI Docker 이미지를 기반으로 하는 컨테이너에서 실행되도록 CI 작업을 업데이트할 수 있습니다. 이 이미지에는 datadog-ci가 사전 설치되어 있어 바로 사용할 수 있습니다.

커버리지 보고서 업로드

Datadog은 백엔드에서 동일한 커밋에 대한 모든 보고서를 자동으로 집계합니다. 커버리지 보고서를 업로드하기 전에 병합할 필요는 없습니다.

코드 커버리지 보고서를 Datadog에 업로드하려면 다음 명령을 실행하세요. 유효한 Datadog API 키(DD_API_KEY)와 커버리지 보고서 파일 또는 해당 파일이 포함된 디렉터리에 대한 하나 이상의 파일 경로를 제공하세요.

Datadog Code Coverage Upload GitHub Action을 사용하세요. 이 액션은 datadog-ci를 자동으로 설치하고 실행하므로 추가 설정이 필요하지 않습니다.


steps:
- name: Upload coverage reports to Datadog
  uses: DataDog/coverage-upload-github-action@v1
  with:
    api_key: ${{ secrets.DD_API_KEY }}
    site: 

또는 datadog-ci가 설치되어 있는 경우 직접 실행할 수 있습니다.


steps:
- name: Upload coverage reports to Datadog
  run: datadog-ci coverage upload .
  env:
    DD_API_KEY: ${{ secrets.DD_API_KEY }}
    DD_SITE: 


test:
  stage: test
  script:
    - ... # run your tests and generate coverage reports
    - datadog-ci coverage upload . # make sure to add the DD_API_KEY CI/CD variable

- script: datadog-ci coverage upload --format=clover coverage/clover.xml displayName: 'Upload coverage to Datadog' env: DD_API_KEY: $(DD_API_KEY) DD_SITE: 'datadoghq.com'

이 명령은 지정된 디렉터리에서 지원되는 커버리지 보고서 파일을 재귀적으로 검색하므로 현재 디렉터리(.)를 지정하는 것으로 충분한 경우가 많습니다. datadog-ci coverage upload 명령에 대한 자세한 내용은 datadog-ci 설명서를 참조하세요.

코드 커버리지 보고서 업로드가 완료된 직후, Datadog은 코드 커버리지 백분율 값이 포함된 PR 코멘트를 추가합니다. 코멘트에 파일별 전체 커버리지 및 패치 커버리지 분석을 추가하려면 PR 코멘트를 참조하세요. 또한 Datadog의 Code Coverage 페이지에서 풀 요청별로 집계된 커버리지 데이터를 조회하고 개별 파일 및 코드 줄을 검토할 수 있습니다.

문제 해결

커버리지 업로드 명령이 커버리지 보고서 파일을 탐지하지 못함

datadog-ci coverage upload 명령은 파일 이름 및 확장자와 같은 추론을 사용하여 지정된 디렉터리에서 지원되는 커버리지 보고서 파일을 자동으로 탐지합니다. 커버리지 보고서 파일이 예상 패턴과 일치하지 않으면 명령이 자동으로 탐지하지 못할 수 있습니다. 이 경우 보고서 형식을 지정하고 파일 경로를 위치 인수로 제공하세요. 예를 들면 다음과 같습니다.

datadog-ci coverage upload --format=lcov \
  src/coverage-reports/unit-tests/coverage.info \
  src/coverage-reports/e2e-tests/coverage.info

커버리지 업로드가 “Format could not be detected” 오류와 함께 실패함

datadog-ci coverage upload 명령은 콘텐츠와 파일 확장자를 기반으로 커버리지 보고서 파일의 형식을 자동으로 탐지합니다. 명령이 다음 오류와 함께 실패하는 경우,

Invalid coverage report file [...]: format could not be detected

다음과 같이 --format 옵션을 사용하여 형식을 명시적으로 지정합니다.

datadog-ci coverage upload --format=cobertura reports/cobertura.xml

커버리지 업로드에서 “Could not sync git metadata” 오류가 발생함

Git 메타데이터 업로드는 CI 공급자를 Datadog과 직접 통합할 수 없는 경우에만 필요합니다. Datadog GitHub 앱이나 Gitlab 통합과 같은 소스 코드 공급자 통합을 사용하는 경우, 다음과 같이 datadog-ci coverage upload 명령에 --skip-git-metadata-upload=1 플래그를 전달하여 Git 메타데이터 업로드를 비활성화할 수 있습니다.

datadog-ci coverage upload --skip-git-metadata-upload=1 .

Datadog UI에서 PR 보기에 변경된 파일이 표시되지 않음

기본적으로 ‘Changed files’ 테이블에는 업로드된 커버리지 보고서에 포함된 실행 가능한 소스 코드 파일만 표시됩니다. 테이블 헤더에서 Non-executable files 또는 All을 선택하면 실행 가능 여부와 관계없이 PR에서 변경된 모든 파일이 표시됩니다.

소스 코드 파일이 실수로 실행 불가능으로 표시된 경우, 업로드된 커버리지 보고서에서 누락되었을 가능성이 높습니다. 관련 보고서를 모두 업로드했는지 확인하고, 커버리지 도구 구성을 다시 확인하여 모든 해당 파일에 대해 커버리지 데이터가 수집되었는지 확인하세요.

테스트 소스는 커버리지를 측정하는 프로덕션 코드베이스의 일부가 아니므로 실행 가능한 파일로 간주되지 않습니다.

Datadog UI에 잘못된 파일 경로가 표시됨

Code Coverage는 커버리지 보고서의 파일 경로가 절대 경로이거나 리포지토리 루트를 기준으로 한 상대 경로여야 합니다. 보고서의 경로가 리포지토리의 다른 디렉터리를 기준으로 하는 경우, datadog-ci coverage upload 명령을 실행할 때 --base-path 옵션을 사용하여 올바른 기본 경로(리포지토리 루트 기준)를 다음과 같이 지정하세요.

datadog-ci coverage upload --base-path=frontend/src .

실행 불가능한 줄로 인한 부정확한 커버리지

일부 커버리지 도구는 보고서에 실행 불가능한 줄(코멘트, 빈 줄, 닫는 괄호 등)을 포함하여 해당 줄을 커버되지 않는 것으로 계산됩니다. 이는 커버리지 백분율을 낮추고 절대 실행될 수 없는 줄에 대해 거짓 부정 결과를 도출할 수 있습니다.

업로드 중 CLI는 소스 파일을 자동으로 스캔하여 이러한 실행 불가능한 줄을 식별하므로 그러한 줄을 커버리지 계산에서 제외할 수 있습니다.

파일 수정은 Go, Kotlin, C/C++, Swift, Objective-C 및 PHP 언어를 지원합니다.

다음 옵션을 사용하여 이 동작을 제어할 수 있습니다.

  • --disable-file-fixes: 파일 수정 생성을 완전히 비활성화합니다.
  • --file-fixes-search-path <dir>: 소스 파일을 스캔하는 데 사용되는 루트 디렉터리를 재정의합니다. 기본적으로 리포지토리 루트가 사용됩니다. 이는 모노레포 환경이거나 커버리지 보고서가 코드베이스의 일부만 다루는 경우, 탐색할 디렉터리 트리를 제한하여 스캔 속도를 높일 수 있으므로 유용합니다.

Datadog UI와 커버리지 보고서 값 간의 불일치

Datadog은 동일한 커밋에 대한 커버리지 보고서를 자동으로 병합합니다. 결과적으로 Datadog UI에 표시되는 커버리지 비율은 개별 커버리지 보고서의 값과 다를 수 있으며, 특히 해당 보고서에 중복되거나 겹치는 소스 코드 파일 항목이 포함된 경우에 그렇습니다.

Datadog에 업로드하기 전에 외부 도구(예: ReportGenerator)를 사용하여 커버리지 보고서를 병합하는 경우, 병합된 보고서에 중복된 소스 코드 파일 항목이 포함되지 않도록 하세요. Datadog은 보고서 간에 겹치는 파일을 중복 제거하며, 이로 인해 원래의 커버리지 값과 Datadog UI에 표시되는 병합된 값 사이에 차이가 발생할 수 있습니다.

보고서가 병합되는 방식과 각 줄 상태가 계산되는 방식에 대한 설명은 코드 커버리지 계산을 참조하세요.

추가 자료