95 lines
3.4 KiB
Python
95 lines
3.4 KiB
Python
# SPDX-FileCopyrightText: 2026 Art Sea LLC
|
|
#
|
|
# SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
"""Coverage-strategy command tests through an explicit in-memory repository."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
from pathlib import Path
|
|
import subprocess
|
|
from typing import Iterable, Sequence
|
|
|
|
from band_aider.context.class_meta import ClassMeta
|
|
from band_aider.judgement.python_ast_dependency_strategy import PythonAstDependencyStrategy
|
|
from band_aider.judgement.python_coverage_strategy import PythonCoverageStrategy
|
|
from band_aider.judgement.test_environment import TEST_ENV_VARIABLES_TO_CLEAR
|
|
from tests.support.memory_repo_exec import MemoryRepoExec
|
|
|
|
|
|
class _CoverageRepoExec(MemoryRepoExec):
|
|
"""In-memory executor that returns a stationary coverage JSON report."""
|
|
|
|
def __init__(self) -> None:
|
|
super().__init__()
|
|
self.environments: list[dict[str, str]] = []
|
|
self.unset_environments: list[tuple[str, ...]] = []
|
|
|
|
def run_cli(
|
|
self,
|
|
command: Sequence[str],
|
|
*,
|
|
cwd: Path | None = None,
|
|
env: dict[str, str] | None = None,
|
|
capture_output: bool = True,
|
|
text: bool = True,
|
|
check: bool = False,
|
|
timeout: int | None = None,
|
|
input: bytes | str | None = None,
|
|
unset_env: Iterable[str] = (),
|
|
) -> subprocess.CompletedProcess:
|
|
"""Record one coverage command and materialize its report in memory."""
|
|
|
|
del cwd, capture_output, text, check, timeout, input
|
|
command_parts = list(command)
|
|
self.environments.append(dict(env or {}))
|
|
self.unset_environments.append(tuple(unset_env))
|
|
if "json" in command_parts:
|
|
output_path = Path(command_parts[command_parts.index("-o") + 1])
|
|
self.write_text(
|
|
output_path,
|
|
json.dumps(
|
|
{
|
|
"files": {
|
|
"src/widget.py": {
|
|
"summary": {
|
|
"covered_branches": 1,
|
|
"num_branches": 1,
|
|
"covered_lines": 1,
|
|
"num_statements": 1,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
),
|
|
)
|
|
return subprocess.CompletedProcess(command_parts, 0, "", "")
|
|
|
|
|
|
def test_python_coverage_strategy_uses_stationary_sanitized_test_environment() -> None:
|
|
"""Verify coverage commands clear host-sensitive variables through the adapter boundary."""
|
|
|
|
repo_exec = _CoverageRepoExec()
|
|
repo_root = repo_exec.root
|
|
src_root = repo_root / "src"
|
|
test_root = repo_root / "tests"
|
|
repo_exec.write_text(test_root / "test_widget.py", "def test_widget():\n assert True\n")
|
|
coverage = PythonCoverageStrategy(
|
|
dependency_strategy=PythonAstDependencyStrategy(),
|
|
repo_exec=repo_exec,
|
|
)
|
|
|
|
assert coverage.branch_coverage_for(
|
|
[ClassMeta("src/widget.py", "", [], {})],
|
|
[ClassMeta("tests/test_widget.py", "", [], {})],
|
|
repo_root,
|
|
src_root,
|
|
test_root,
|
|
) == 1.0
|
|
assert len(repo_exec.environments) == 2
|
|
assert all(set(environment) == {"COVERAGE_FILE"} for environment in repo_exec.environments)
|
|
assert repo_exec.unset_environments == [
|
|
TEST_ENV_VARIABLES_TO_CLEAR,
|
|
TEST_ENV_VARIABLES_TO_CLEAR,
|
|
]
|