8Tests for ``oct format --changed`` (Phase 4C — G-C2).
12- Verify that ``--changed`` formats only git-modified Python files.
13- Verify graceful behaviour in non-git directories.
14- Verify JSON output mode with ``--changed``.
21 L3 — assertion details
26- All tests use tmp_path so they are automatically cleaned up.
33from pathlib
import Path
44 return shutil.which(
"git")
is not None
47def _git(repo: Path, *args: str, check: bool =
True):
48 return subprocess.run(
58 """Create a git repo with pyproject.toml and one committed Python file."""
59 root = tmp_path /
"fmtproj"
61 (root /
"src").mkdir()
62 (root /
"tests").mkdir()
63 (root /
"docs").mkdir()
64 (root /
"oc_diagnostics").mkdir()
65 (root /
"pyproject.toml").write_text(
66 '[project]\nname = "fmtproj"\n', encoding=
"utf-8",
70 compliant = textwrap.dedent(
"""\
71 #!/usr/bin/env python3
72 # -*- coding: utf-8 -*-
98 from oc_diagnostics import _dbg
102 (root /
"src" /
"clean.py").write_text(compliant, encoding=
"utf-8")
104 _git(root,
"init",
"--quiet",
"-b",
"main")
105 _git(root,
"config",
"user.email",
"test@example.com")
106 _git(root,
"config",
"user.name",
"Test")
107 _git(root,
"config",
"commit.gpgsign",
"false")
108 _git(root,
"add",
"-A")
109 _git(root,
"commit",
"-m",
"initial",
"--quiet")
120 @pytest.mark.skipif(not _git_available(), reason=
"git not on PATH")
122 """--changed with a clean working tree → no modified files."""
126 result = run_formatter(root, [
"--changed"])
127 assert result
is None
129 @pytest.mark.skipif(not _git_available(), reason=
"git not on PATH")
131 """--changed with one modified file → that file is formatted."""
135 dirty = (root /
"src" /
"clean.py").read_text(encoding=
"utf-8")
136 (root /
"src" /
"clean.py").write_text(dirty +
"\ny = 2\n", encoding=
"utf-8")
139 run_formatter(root, [
"--changed"])
140 captured = capsys.readouterr()
142 assert "1" in captured.out
or "clean.py" in captured.out
144 @pytest.mark.skipif(not _git_available(), reason=
"git not on PATH")
146 """--changed should NOT process files without modifications."""
150 new_file = root /
"src" /
"added.py"
151 new_file.write_text(
"# added\nx = 1\n", encoding=
"utf-8")
154 run_formatter(root, [
"--changed"])
155 captured = capsys.readouterr()
157 assert "clean.py" not in captured.out
or "1" in captured.out
159 @pytest.mark.skipif(not _git_available(), reason=
"git not on PATH")
161 """--changed --json produces valid JSON."""
163 dirty = (root /
"src" /
"clean.py").read_text(encoding=
"utf-8")
164 (root /
"src" /
"clean.py").write_text(dirty +
"\nz = 3\n", encoding=
"utf-8")
167 run_formatter(root, [
"--changed",
"--json"])
168 captured = capsys.readouterr()
169 data = json.loads(captured.out)
170 assert "files" in data
171 assert isinstance(data[
"files"], list)
174 """--changed on a non-git directory → graceful empty result."""
175 root = tmp_path /
"nogit"
177 (root /
"pyproject.toml").write_text(
178 '[project]\nname = "nogit"\n', encoding=
"utf-8",
180 (root /
"src").mkdir()
181 (root /
"src" /
"x.py").write_text(
"x = 1\n", encoding=
"utf-8")
184 result = run_formatter(root, [
"--changed"])
185 assert result
is None
187 @pytest.mark.skipif(not _git_available(), reason=
"git not on PATH")
189 """--changed --fix should apply fixes only to changed files."""
193 bad = root /
"src" /
"bad.py"
194 bad.write_text(
"# bad file\nx = 1\n", encoding=
"utf-8")
197 run_formatter(root, [
"--changed",
"--fix"])
198 content = bad.read_text(encoding=
"utf-8")
200 assert "#!/usr/bin/env python3" in content