Option C Tools
Loading...
Searching...
No Matches
test_git_health.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3# tests/tests_git/test_git_health.py
4
5"""
6Purpose
7-------
8Tests for the git health section in ``oct health`` (Phase 4E — G-E5, G-E10).
9
10Responsibilities
11----------------
12- Validate ``check_git_health`` returns correct statuses.
13- Verify graceful degradation when git is absent or not a repo.
14
15Diagnostics
16-----------
17Domain: GIT-TESTS
18Levels:
19 L2 — test lifecycle
20 L3 — test details
21 L4 — deep tracing
22
23Contracts
24---------
25- Uses ``temp_git_project`` fixture for real git repo scenarios.
26- Non-repo scenarios use bare tmp_path.
27"""
28
29import json
30import shutil
31from pathlib import Path
32
33import pytest
34
35from tests_git.conftest import _git, _git_available, commit_file
36
37
38pytestmark = pytest.mark.skipif(
39 not _git_available(), reason="git binary not available on PATH",
40)
41
42
43# =====================================================================
44# TestGitHealth
45# =====================================================================
46
47
49 """Tests for check_git_health()."""
50
51 def test_is_repo_ok(self, temp_git_project: Path) -> None:
52 from oct.health.oct_health import check_git_health
53 result = check_git_health(temp_git_project)
54 assert result["is_repo"]["status"] == "OK"
55
56 def test_not_a_repo(self, tmp_path: Path) -> None:
57 from oct.health.oct_health import check_git_health
58 result = check_git_health(tmp_path)
59 assert result["is_repo"]["status"] == "FAIL"
60 # All other checks should be SKIP.
61 for key in ("branch", "naming_conformant", "clean_worktree",
62 "ahead_behind", "hooks_installed", "last_commit_conventional"):
63 assert result[key]["status"] == "SKIP"
64
65 def test_clean_worktree_ok(self, temp_git_project: Path) -> None:
66 from oct.health.oct_health import check_git_health
67 result = check_git_health(temp_git_project)
68 assert result["clean_worktree"]["status"] == "OK"
69
70 def test_dirty_worktree_warn(self, temp_git_project: Path) -> None:
71 from oct.health.oct_health import check_git_health
72 # Create an unstaged change.
73 (temp_git_project / "src" / "dirty.py").write_text("# dirty\n", encoding="utf-8")
74 _git(temp_git_project, "add", "src/dirty.py")
75 result = check_git_health(temp_git_project)
76 assert result["clean_worktree"]["status"] == "WARN"
77
78 def test_conventional_last_commit_ok(self, temp_git_project: Path) -> None:
79 from oct.health.oct_health import check_git_health
80 _git(temp_git_project, "checkout", "-b", "feature/conv")
81 commit_file(temp_git_project, "src/conv.py", "# conv\n", "feat: conventional commit")
82 result = check_git_health(temp_git_project)
83 assert result["last_commit_conventional"]["status"] == "OK"
84
85 def test_non_conventional_last_commit_warn(self, temp_git_project: Path) -> None:
86 from oct.health.oct_health import check_git_health
87 # The initial commit is "initial: project structure" which is conventional-ish
88 # but type "initial" is not in COMMIT_TYPES. Let's make a non-conventional one.
89 _git(temp_git_project, "checkout", "-b", "feature/nonconv")
90 commit_file(temp_git_project, "src/nc.py", "# nc\n", "just a random commit")
91 result = check_git_health(temp_git_project)
92 assert result["last_commit_conventional"]["status"] == "WARN"
93
94 def test_valid_branch_name_ok(self, temp_git_project: Path) -> None:
95 from oct.health.oct_health import check_git_health
96 _git(temp_git_project, "checkout", "-b", "feature/valid-name")
97 result = check_git_health(temp_git_project)
98 assert result["naming_conformant"]["status"] == "OK"
99
100 def test_invalid_branch_name_warn(self, temp_git_project: Path) -> None:
101 from oct.health.oct_health import check_git_health
102 _git(temp_git_project, "checkout", "-b", "bad-name")
103 result = check_git_health(temp_git_project)
104 assert result["naming_conformant"]["status"] == "WARN"
105
106 def test_hooks_missing_warn(self, temp_git_project: Path) -> None:
107 from oct.health.oct_health import check_git_health
108 # No .pre-commit-config.yaml by default.
109 result = check_git_health(temp_git_project)
110 assert result["hooks_installed"]["status"] == "WARN"
111
112 def test_branch_present(self, temp_git_project: Path) -> None:
113 from oct.health.oct_health import check_git_health
114 result = check_git_health(temp_git_project)
115 assert result["branch"]["status"] == "OK"
116 assert result["branch"]["detail"] == "main"
117
118 def test_run_health_includes_git(self, temp_git_project: Path) -> None:
119 """Integration: run_health report includes git section."""
120 from oct.health.oct_health import run_health
121 import io
122 import contextlib
123
124 # Capture output — run_health prints to stdout.
125 f = io.StringIO()
126 with contextlib.redirect_stdout(f):
127 run_health(temp_git_project, json_mode=True)
128
129 output = f.getvalue()
130 data = json.loads(output)
131 assert "git" in data
132 assert "is_repo" in data["git"]
None test_non_conventional_last_commit_warn(self, Path temp_git_project)
None test_valid_branch_name_ok(self, Path temp_git_project)
None test_conventional_last_commit_ok(self, Path temp_git_project)
None test_hooks_missing_warn(self, Path temp_git_project)
None test_is_repo_ok(self, Path temp_git_project)
None test_branch_present(self, Path temp_git_project)
None test_run_health_includes_git(self, Path temp_git_project)
None test_invalid_branch_name_warn(self, Path temp_git_project)
None test_clean_worktree_ok(self, Path temp_git_project)
None test_not_a_repo(self, Path tmp_path)
None test_dirty_worktree_warn(self, Path temp_git_project)