gitlink-cli/examples/research/repro-audit/tests/test_audit.py

100 lines
3.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""确定性回归护栏:同输入 → 同分 → 同等级。"""
import sys
import tempfile
import unittest
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "scripts"))
from repro_audit import audit, read_repos_file, render_report, render_summary # noqa: E402
GOOD_README = """# Project
## How to run
```bash
make train
```
## Dataset
Download the dataset from ...
## Citation
```bibtex
@article{x2026}
```
"""
class AuditTest(unittest.TestCase):
def test_full_marks(self):
names = ["README.md", "LICENSE", "CITATION.cff", "requirements.txt", "Makefile"]
dirs = ["data", "tests", "src"]
results = audit(names, dirs, GOOD_README, release_count=2)
report, total = render_report("o", "r", "", results)
self.assertEqual(total, 100)
self.assertIn("等级 A", report)
def test_empty_repo(self):
results = audit([], [], "", release_count=0)
report, total = render_report("o", "r", "", results)
self.assertEqual(total, 0)
self.assertIn("等级 D", report)
def test_readme_without_usage_partial(self):
results = audit(["README.md"], [], "# hi", release_count=0)
readme = next(r for r in results if r.name == "README 与运行说明")
self.assertEqual(readme.score, 8) # 有 README 无运行说明 → 部分分
def test_citation_in_readme_counts(self):
results = audit(["README.md"], [], "## Citation\n@article{x}", release_count=0)
cit = next(r for r in results if r.name == "引用信息")
self.assertEqual(cit.score, cit.weight)
def test_scripts_dir_as_entry(self):
results = audit([], ["scripts"], "", release_count=0)
entry = next(r for r in results if r.name == "运行入口")
self.assertEqual(entry.score, entry.weight)
def test_deterministic(self):
a = audit(["README.md", "go.mod"], ["tests"], GOOD_README, 1)
b = audit(["README.md", "go.mod"], ["tests"], GOOD_README, 1)
self.assertEqual([vars(x) for x in a], [vars(y) for y in b])
def test_advice_present_for_failures(self):
results = audit([], [], "", 0)
for r in results:
self.assertTrue(r.advice, f"{r.name} 应给出修复建议")
def test_read_repos_file(self):
with tempfile.NamedTemporaryFile("w", suffix=".txt", delete=False, encoding="utf-8") as f:
f.write("# 注释\n\nowner1/repo1\n owner2/repo2 \n")
path = f.name
self.assertEqual(read_repos_file(path), [("owner1", "repo1"), ("owner2", "repo2")])
def test_read_repos_file_invalid_line(self):
with tempfile.NamedTemporaryFile("w", suffix=".txt", delete=False, encoding="utf-8") as f:
f.write("not-a-repo-line\n")
path = f.name
with self.assertRaises(ValueError):
read_repos_file(path)
def test_render_summary_sorted(self):
summary = render_summary([("o/low", 8), ("o/high", 92), ("o/mid", 58)])
rows = [line for line in summary.splitlines() if line.startswith("| o/")]
self.assertEqual([r.split(" | ")[0] for r in rows], ["| o/high", "| o/mid", "| o/low"])
self.assertIn("A可复现性良好", rows[0])
self.assertIn("D复现困难", rows[2])
def test_render_summary_lists_failures(self):
summary = render_summary([("o/ok", 80)], failures=[("o/broken", "仓库树读取失败")])
self.assertIn("## 无法审计的仓库", summary)
self.assertIn("- o/broken仓库树读取失败", summary)
if __name__ == "__main__":
unittest.main()