Files
local-llm-prompt-manager/repohealth-cli/tests/test_reporters.py

262 lines
8.8 KiB
Python

"""Tests for reporter modules."""
import json
from repohealth.models.file_stats import FileAnalysis
from repohealth.models.result import RepositoryResult
from repohealth.reporters.html_reporter import HTMLReporter
from repohealth.reporters.json_reporter import JSONReporter
class TestJSONReporter:
"""Tests for JSONReporter."""
def setup_method(self):
"""Set up test fixtures."""
self.reporter = JSONReporter()
self.sample_result = RepositoryResult(
repository_path="/test/repo",
files_analyzed=10,
total_commits=100,
unique_authors=5,
overall_bus_factor=2.5,
gini_coefficient=0.35,
files=[
{
"path": "src/main.py",
"total_commits": 20,
"num_authors": 2,
"author_commits": {"a@x.com": 15, "b@x.com": 5},
"bus_factor": 1.5,
"risk_level": "high",
"top_author_share": 0.75,
"module": "src",
"extension": "py"
}
],
hotspots=[
{
"file_path": "src/main.py",
"risk_level": "high",
"bus_factor": 1.5,
"top_author": "a@x.com",
"top_author_share": 0.75,
"total_commits": 20,
"num_authors": 2,
"module": "src",
"suggestion": "Consider code reviews"
}
],
suggestions=[
{
"file_path": "src/main.py",
"current_author": "a@x.com",
"suggested_authors": ["b@x.com"],
"priority": "high",
"reason": "High ownership concentration",
"action": "Assign reviews to b@x.com"
}
],
risk_summary={
"critical": 0,
"high": 1,
"medium": 3,
"low": 6,
"percentage_critical": 0.0,
"percentage_high": 10.0,
"overall_risk": "low"
}
)
def test_generate_json(self):
"""Test JSON generation."""
json_output = self.reporter.generate(self.sample_result)
assert isinstance(json_output, str)
parsed = json.loads(json_output)
assert parsed["repository"] == "/test/repo"
assert parsed["summary"]["overall_bus_factor"] == 2.5
def test_generate_file_dict(self):
"""Test file analysis to dictionary conversion."""
analysis = FileAnalysis(
path="src/main.py",
total_commits=20,
author_commits={"a@x.com": 15, "b@x.com": 5},
bus_factor=1.5,
risk_level="high",
module="src",
extension="py"
)
file_dict = self.reporter.generate_file_dict(analysis)
assert file_dict["path"] == "src/main.py"
assert file_dict["total_commits"] == 20
assert file_dict["num_authors"] == 2
assert file_dict["bus_factor"] == 1.5
def test_save_json(self, temp_dir):
"""Test saving JSON to file."""
output_file = temp_dir / "output.json"
self.reporter.save(self.sample_result, str(output_file))
assert output_file.exists()
content = json.loads(output_file.read_text())
assert content["repository"] == "/test/repo"
def test_indent_parameter(self):
"""Test JSON indentation."""
reporter_no_indent = JSONReporter(indent=0)
json_output = reporter_no_indent.generate(self.sample_result)
lines = json_output.strip().split("\n")
assert len(lines) <= 2
def test_json_contains_required_fields(self):
"""Test that JSON output contains all required fields."""
json_output = self.reporter.generate(self.sample_result)
parsed = json.loads(json_output)
assert "version" in parsed
assert "repository" in parsed
assert "analyzed_at" in parsed
assert "summary" in parsed
assert "files" in parsed
assert "hotspots" in parsed
assert "suggestions" in parsed
class TestHTMLReporter:
"""Tests for HTMLReporter."""
def setup_method(self):
"""Set up test fixtures."""
self.reporter = HTMLReporter()
self.sample_result = RepositoryResult(
repository_path="/test/repo",
files_analyzed=10,
total_commits=100,
unique_authors=5,
overall_bus_factor=2.5,
gini_coefficient=0.35,
files=[
{
"path": "src/main.py",
"total_commits": 20,
"num_authors": 2,
"author_commits": {"a@x.com": 15, "b@x.com": 5},
"bus_factor": 1.5,
"risk_level": "high",
"top_author_share": 0.75,
"module": "src",
"extension": "py"
}
],
hotspots=[
{
"file_path": "src/main.py",
"risk_level": "high",
"bus_factor": 1.5,
"top_author": "a@x.com",
"top_author_share": 0.75,
"total_commits": 20,
"num_authors": 2,
"module": "src",
"suggestion": "Consider code reviews"
}
],
suggestions=[
{
"file_path": "src/main.py",
"current_author": "a@x.com",
"suggested_authors": ["b@x.com"],
"priority": "high",
"reason": "High ownership concentration",
"action": "Assign reviews to b@x.com"
}
],
risk_summary={
"critical": 0,
"high": 1,
"medium": 3,
"low": 6,
"percentage_critical": 0.0,
"percentage_high": 10.0,
"overall_risk": "low"
}
)
def test_generate_standalone(self):
"""Test standalone HTML generation."""
html_output = self.reporter.generate_standalone(self.sample_result)
assert isinstance(html_output, str)
assert "<!doctype html>" in html_output.lower() or "<html>" in html_output.lower()
assert "</html>" in html_output
def test_standalone_contains_summary(self):
"""Test that standalone HTML contains summary section."""
html_output = self.reporter.generate_standalone(self.sample_result)
assert "repository health report" in html_output.lower()
def test_standalone_contains_chart_data(self):
"""Test that standalone HTML includes Chart.js."""
html_output = self.reporter.generate_standalone(self.sample_result)
assert "chart.js" in html_output.lower()
def test_save_standalone(self, temp_dir):
"""Test saving standalone HTML to file."""
output_file = temp_dir / "report.html"
self.reporter.save_standalone(self.sample_result, str(output_file))
assert output_file.exists()
content = output_file.read_text()
assert "<!doctype html>" in content.lower() or "<html>" in content.lower()
def test_generate_charts_data(self):
"""Test chart data generation."""
charts_data = self.reporter.generate_charts_data(self.sample_result)
assert "risk_distribution" in charts_data
assert "top_hotspots" in charts_data
assert "file_data" in charts_data
assert "summary" in charts_data
def test_risk_colors_defined(self):
"""Test that risk colors are properly defined."""
assert "critical" in self.reporter.RISK_COLORS
assert "high" in self.reporter.RISK_COLORS
assert "medium" in self.reporter.RISK_COLORS
assert "low" in self.reporter.RISK_COLORS
class TestTerminalReporter:
"""Tests for TerminalReporter."""
def test_reporter_initialization(self):
"""Test terminal reporter initialization."""
from repohealth.reporters.terminal import TerminalReporter
reporter = TerminalReporter()
assert reporter.RISK_COLORS is not None
def test_risk_colors_mapping(self):
"""Test risk color mappings."""
from repohealth.reporters.terminal import TerminalReporter
reporter = TerminalReporter()
assert reporter.RISK_COLORS["critical"] == "red"
assert reporter.RISK_COLORS["high"] == "orange3"
assert reporter.RISK_COLORS["medium"] == "yellow"
assert reporter.RISK_COLORS["low"] == "green"