Source code for tests.test_coverage_floor

# Copyright Kevin Deldycke <[email protected]> and contributors.
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

"""Tests for `lint-coverage`: the coverage floor against the coverage total."""

from __future__ import annotations

import json

import pytest
from click_extra.testing import CliRunner

from repomatic.cli.ci import COVERAGE_FLOOR_SLACK
from repomatic.cli.main import repomatic

TYPE_CHECKING = False
if TYPE_CHECKING:
    from pathlib import Path

    from click.testing import Result


[docs] @pytest.fixture def project(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> Path: """An empty project directory, as the working directory.""" monkeypatch.chdir(tmp_path) return tmp_path
def _lint_coverage( project: Path, floor: float | None, total: float | None, *args: str ) -> Result: """Run `lint-coverage` against a floor and a report total. :param project: The working directory to write the two files in. :param floor: The `report.fail_under` value, or `None` to declare none. :param total: The total of `coverage.json`, or `None` to write no report. :param args: Extra arguments of the command. """ config = '[project]\nname = "papaya"\n' if floor is not None: config += f"\n[tool.coverage]\nreport.fail_under = {floor}\n" (project / "pyproject.toml").write_text(config, encoding="UTF-8") if total is not None: (project / "coverage.json").write_text( json.dumps({"totals": {"percent_covered": total}}), encoding="UTF-8" ) return CliRunner().invoke(repomatic, ["lint-coverage", *args])
[docs] @pytest.mark.parametrize( ("headroom", "lags"), ((0.5, False), (COVERAGE_FLOOR_SLACK, False), (COVERAGE_FLOOR_SLACK + 0.01, True)), ) def test_floor_lags_past_the_slack(project: Path, headroom: float, lags: bool) -> None: """A floor further under the total than the slack fails the check.""" result = _lint_coverage(project, 90, 90 + headroom) assert result.exit_code == (1 if lags else 0), result.output assert ("✓ The 90% floor keeps within" in result.output) is not lags
[docs] @pytest.mark.parametrize( ("args", "exit_code", "annotation"), (([], 1, "::error"), (["--no-fatal"], 0, "::warning")), ) def test_lagging_floor_warns_without_fatal( project: Path, args: list[str], exit_code: int, annotation: str ) -> None: """`--no-fatal` turns the failure into a warning, with the same message.""" result = _lint_coverage(project, 80, 92.24, *args) assert result.exit_code == exit_code, result.output assert annotation in result.output assert "sits 12.24 points under the 92.24% coverage total" in result.output
[docs] @pytest.mark.parametrize( ("floor", "total", "message"), ( (93, None, "No coverage report at"), (None, 94.2, "No [tool.coverage] report.fail_under floor"), (0, 94.2, "No [tool.coverage] report.fail_under floor"), ), ) def test_nothing_to_compare_passes( project: Path, floor: float | None, total: float | None, message: str ) -> None: """With no report or no floor, the check passes and says why.""" result = _lint_coverage(project, floor, total) assert result.exit_code == 0, result.output assert message in result.output
[docs] def test_unreadable_report_fails_cleanly(project: Path) -> None: """A report with no total ends on an error message, not a traceback.""" (project / "coverage.json").write_text("{}", encoding="UTF-8") result = _lint_coverage(project, 93, None) assert result.exit_code == 1, result.output assert isinstance(result.exception, SystemExit) assert "Cannot compare" in result.output