from __future__ import annotations from pathlib import Path import textwrap from testing.quality_contract import load_contract from testing.quality_coverage import run_check as run_coverage_check from testing.quality_docs import run_check as run_docs_check from testing.quality_hygiene import run_check as run_hygiene_check def test_bundled_contract_exposes_local_and_jenkins_profiles(): contract = load_contract() assert "local" in contract["profiles"] assert "jenkins" in contract["profiles"] assert contract["pytest_suites"]["unit"]["paths"] def test_bundled_contract_keeps_monorepo_manifest_trees_out_of_hygiene_scope(): contract = load_contract() required_doc_paths = {item["path"] for item in contract.get("required_docs", [])} assert "AGENTS.md" not in required_doc_paths globs = contract.get("hygiene", {}).get("line_limit_globs", []) assert globs for entry in globs: assert entry.startswith(("testing/", "ci/", "scripts/tests/", "services/")) assert "/scripts/" in entry or not entry.startswith("services/") def test_docs_check_reports_missing_docstring_and_missing_path(tmp_path: Path): module_path = tmp_path / "managed.py" module_path.write_text("value = 1\n", encoding="utf-8") (tmp_path / "README.md").write_text("repo docs\n", encoding="utf-8") contract = { "required_docs": [{"path": "README.md", "description": "Docs"}], "managed_modules": ["managed.py"], "lint_paths": ["missing-dir"], "pytest_suites": {"unit": {"description": "Unit", "paths": ["missing-tests"]}}, "manual_scripts": [{"path": "missing-script.py", "description": "Manual"}], } issues = run_docs_check(contract, tmp_path) assert "module docstring missing: managed.py" in issues assert "contract path missing: missing-dir" in issues assert "contract path missing: missing-tests" in issues assert "contract path missing: missing-script.py" in issues def test_docs_check_reports_missing_required_doc_metadata(tmp_path: Path): (tmp_path / "README.md").write_text("", encoding="utf-8") contract = { "required_docs": [{"path": "README.md", "description": ""}, {"path": "missing.md", "description": "Missing"}], "managed_modules": [], "lint_paths": [], "pytest_suites": {"unit": {"description": "", "paths": []}}, "manual_scripts": [{"path": "manual.py", "description": ""}], } issues = run_docs_check(contract, tmp_path) assert "required doc empty: README.md" in issues assert "required doc missing description: README.md" in issues assert "required doc missing: missing.md" in issues assert "pytest suite missing description: unit" in issues assert "manual script missing description: manual.py" in issues def test_hygiene_check_enforces_line_limit_and_name_rules(tmp_path: Path): tests_dir = tmp_path / "tests" tests_dir.mkdir() bad_name = tests_dir / "bad-name.py" bad_name.write_text("x = 1\n", encoding="utf-8") long_file = tests_dir / "test_too_long.py" long_file.write_text("line\n" * 4, encoding="utf-8") contract = { "hygiene": { "max_lines": 3, "line_limit_globs": ["tests/*.py"], "naming_rules": [ { "glob": "tests/*.py", "pattern": r"^test_[a-z0-9_]+\.py$", "description": "pytest files use test_*.py names.", } ], } } issues = run_hygiene_check(contract, tmp_path) assert any("file exceeds 3 LOC" in issue for issue in issues) assert any("naming rule failed" in issue and "bad-name.py" in issue for issue in issues) def test_coverage_check_enforces_per_file_floor(tmp_path: Path): build_dir = tmp_path / "build" build_dir.mkdir() coverage_xml = build_dir / "coverage.xml" coverage_xml.write_text( textwrap.dedent( """\ """ ), encoding="utf-8", ) contract = { "coverage": { "minimum_percent": 95.0, "tracked_files": ["ok.py", "low.py", "missing.py"], } } issues = run_coverage_check(contract, tmp_path, coverage_xml) assert "coverage below 95.0%: low.py (90.0%)" in issues assert "coverage missing for tracked file: missing.py" in issues def test_coverage_check_handles_missing_xml_and_source_root_mapping(tmp_path: Path): missing_xml = tmp_path / "missing.xml" assert run_coverage_check({"coverage": {"tracked_files": []}}, tmp_path, missing_xml) == [ "coverage xml missing: missing.xml" ] source_dir = tmp_path / "pkg" source_dir.mkdir() (source_dir / "mapped.py").write_text("value = 1\n", encoding="utf-8") coverage_xml = tmp_path / "coverage.xml" coverage_xml.write_text( textwrap.dedent( f"""\ {source_dir} """ ), encoding="utf-8", ) (tmp_path / "absolute.py").write_text("value = 2\n", encoding="utf-8") issues = run_coverage_check( { "coverage": { "minimum_percent": 95.0, "tracked_files": ["pkg/mapped.py", "absolute.py"], } }, tmp_path, coverage_xml, ) assert issues == []