fix: update CI workflow with proper checkout paths
This commit is contained in:
261
tests/test_reporters.py
Normal file
261
tests/test_reporters.py
Normal file
@@ -0,0 +1,261 @@
|
||||
"""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"
|
||||
Reference in New Issue
Block a user