Skip to content

Commit

Permalink
Branch coverage WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
ewjoachim committed May 26, 2024
1 parent bddb8d0 commit 1a43165
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 8 deletions.
13 changes: 13 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,16 @@ To run the end-to-end tests, you'll need:
- Please be aware that the tests will launch `gh auth setup-git` which might be
surprising if you use `https` remotes (sadly, setting `GIT_CONFIG_GLOBAL`
seems not to be enough to isolate tests.)

## Coverage labs

### Computing the coverage rate

The coverage rate is `covered_lines / total_lines` (as one would expect).
In case "branch coverage" is enabled, the coverage rate is
`(covered_lines + covered_branches) / (total_lines + total_branches)`.
In order to display coverage rates, we need to round the values. Depending on
the situation, we either round to 0 or 2 decimal places. Rounding rules are:
- We always round down (truncate) the value.
- We don't display the trailing zeros in the decimal part (nor the decimal point
if the decimal part is 0).
55 changes: 47 additions & 8 deletions coverage_comment/coverage.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import json
import pathlib
from collections.abc import Sequence
from typing import cast

from coverage_comment import log, subprocess

Expand Down Expand Up @@ -40,6 +41,8 @@ class FileCoverage:
executed_lines: list[int]
missing_lines: list[int]
excluded_lines: list[int]
executed_branches: list[list[int]] | None
missing_branches: list[list[int]] | None
info: CoverageInfo


Expand Down Expand Up @@ -82,10 +85,26 @@ class DiffCoverage:
files: dict[pathlib.Path, FileDiffCoverage]


def compute_coverage(num_covered: int, num_total: int) -> decimal.Decimal:
if num_total == 0:
def compute_coverage(
num_covered: int,
num_total: int,
use_branch_coverage: bool,
num_branches_covered: int | None,
num_branches_total: int | None,
) -> decimal.Decimal:
"""Compute the coverage percentage, with or without branch coverage."""
if use_branch_coverage:
num_branches_covered = cast(int, num_branches_covered)
num_branches_total = cast(int, num_branches_total)
numerator = decimal.Decimal(num_covered + num_branches_covered)
denominator = decimal.Decimal(num_total + num_branches_total)
else:
numerator = decimal.Decimal(num_covered)
denominator = decimal.Decimal(num_total)

if denominator == 0:
return decimal.Decimal("1")
return decimal.Decimal(num_covered) / decimal.Decimal(num_total)
return numerator / denominator


def get_coverage_info(
Expand Down Expand Up @@ -191,12 +210,19 @@ def extract_info(data: dict, coverage_path: pathlib.Path) -> Coverage:
excluded_lines=file_data["excluded_lines"],
executed_lines=file_data["executed_lines"],
missing_lines=file_data["missing_lines"],
executed_branches=file_data.get("executed_branches"),
missing_branches=file_data.get("missing_branches"),
info=CoverageInfo(
covered_lines=file_data["summary"]["covered_lines"],
num_statements=file_data["summary"]["num_statements"],
percent_covered=compute_coverage(
file_data["summary"]["covered_lines"],
file_data["summary"]["num_statements"],
num_covered=file_data["summary"]["covered_lines"],
num_total=file_data["summary"]["num_statements"],
use_branch_coverage=data["meta"]["branch_coverage"],
num_branches_covered=file_data["summary"].get(
"covered_branches"
),
num_branches_total=file_data["summary"].get("num_branches"),
),
missing_lines=file_data["summary"]["missing_lines"],
excluded_lines=file_data["summary"]["excluded_lines"],
Expand All @@ -214,8 +240,11 @@ def extract_info(data: dict, coverage_path: pathlib.Path) -> Coverage:
covered_lines=data["totals"]["covered_lines"],
num_statements=data["totals"]["num_statements"],
percent_covered=compute_coverage(
data["totals"]["covered_lines"],
data["totals"]["num_statements"],
num_covered=data["totals"]["covered_lines"],
num_total=data["totals"]["num_statements"],
use_branch_coverage=data["meta"]["branch_coverage"],
num_branches_covered=data["totals"].get("covered_branches"),
num_branches_total=data["totals"].get("num_branches"),
),
missing_lines=data["totals"]["missing_lines"],
excluded_lines=data["totals"]["excluded_lines"],
Expand Down Expand Up @@ -255,8 +284,18 @@ def get_diff_coverage_info(
total_num_lines += count_total
total_num_violations += count_missing

num_branches_covered = None
num_branches_total = None
if coverage.meta.branch_coverage:
num_branches_covered = 12
num_branches_total = 12

percent_covered = compute_coverage(
num_covered=count_executed, num_total=count_total
num_covered=count_executed,
num_total=count_total,
use_branch_coverage=coverage.meta.branch_coverage,
num_branches_covered=num_branches_covered,
num_branches_total=num_branches_total,
)

files[path] = FileDiffCoverage(
Expand Down

0 comments on commit 1a43165

Please sign in to comment.