Option C Tools
Loading...
Searching...
No Matches
test_header_fixing.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3# tests/tests_formatter/test_header_fixing.py
4
5"""
6Tests for header block fixing.
7
8Purpose
9-------
10Verify that the formatter correctly fixes malformed header blocks.
11
12Responsibilities
13----------------
14- Test missing shebang fixes.
15- Test missing encoding fixes.
16- Test incorrect file identity fixes.
17- Test missing blank line fixes.
18- Verify archival of original files.
19- Verify code preservation.
20
21Diagnostics
22-----------
23Domain: TESTS.FORMATTER
24Levels:
25 L2 — test lifecycle
26 L3 — test case setup
27 L4 — detailed assertion checks
28
29Contracts
30---------
31- All tests verify that fix_header_block returns (True, new_text, messages) when changes are needed.
32- All tests verify that original files are archived before modification.
33"""
34
35import pytest
36from pathlib import Path
37
38from oct.formatter.oct_format import fix_header_block, FormatterContext
39
40
41def test_fix_missing_shebang(temp_project_root: Path, formatter_ctx_fix: FormatterContext):
42 """Test that missing shebang is added correctly."""
43 test_file = temp_project_root / "test_missing_shebang.py"
44 test_file.write_text(
45 "# -*- coding: utf-8 -*-\n"
46 "# test.py\n"
47 "\n"
48 "print('hello')\n",
49 encoding="utf-8"
50 )
51
52 changed, new_text, messages = fix_header_block(test_file, test_file.read_text(encoding="utf-8"), formatter_ctx_fix)
53
54 assert changed is True
55 assert len(messages) > 0
56 assert new_text.startswith("#!/usr/bin/env python3\n")
57
58
59def test_fix_missing_encoding(temp_project_root: Path, formatter_ctx_fix: FormatterContext):
60 """Test that missing encoding is added correctly."""
61 test_file = temp_project_root / "test_missing_encoding.py"
62 test_file.write_text(
63 "#!/usr/bin/env python3\n"
64 "# test.py\n"
65 "\n"
66 "print('hello')\n",
67 encoding="utf-8"
68 )
69
70 changed, new_text, messages = fix_header_block(test_file, test_file.read_text(encoding="utf-8"), formatter_ctx_fix)
71
72 assert changed is True
73 lines = new_text.split('\n')
74 assert lines[1] == "# -*- coding: utf-8 -*-"
75
76
77def test_fix_wrong_path_header(temp_project_root: Path, formatter_ctx_fix: FormatterContext):
78 """Test that incorrect file path header is rewritten."""
79 test_file = temp_project_root / "test_wrong_path.py"
80 test_file.write_text(
81 "#!/usr/bin/env python3\n"
82 "# -*- coding: utf-8 -*-\n"
83 "# wrong/path/to/file.py\n"
84 "\n"
85 "print('hello')\n",
86 encoding="utf-8"
87 )
88
89 changed, new_text, messages = fix_header_block(test_file, test_file.read_text(encoding="utf-8"), formatter_ctx_fix)
90
91 assert changed is True
92 lines = new_text.split('\n')
93 assert "test_wrong_path.py" in lines[2]
94
95
96def test_header_archives_original(temp_project_root: Path, formatter_ctx_fix: FormatterContext):
97 """Test that format_file archives original before writing (archival moved to format_file)."""
98 from oct.formatter.oct_format import format_file
99 test_file = temp_project_root / "test_archive.py"
100 original_content = (
101 "# Missing header\n"
102 "print('hello')\n"
103 )
104 test_file.write_text(original_content, encoding="utf-8")
105
106 result = format_file(test_file, formatter_ctx_fix)
107
108 assert result["changed"] is True
109 archive_dir = test_file.parent / ".formatter_archive"
110 assert archive_dir.exists()
111 backups = list(archive_dir.glob("test_archive.py.*"))
112 assert len(backups) == 1
113 assert backups[0].read_text(encoding="utf-8") == original_content
114
115
116def test_header_preserves_code(temp_project_root: Path, formatter_ctx_fix: FormatterContext):
117 """Test that code below header is preserved exactly."""
118 test_file = temp_project_root / "test_preserve.py"
119 code_content = """def my_function():
120 '''
121 Multi-line
122 docstring
123 '''
124 x = 1
125 y = 2
126 return x + y
127"""
128 test_file.write_text(
129 "# Missing header\n"
130 + code_content,
131 encoding="utf-8"
132 )
133
134 changed, new_text, messages = fix_header_block(test_file, test_file.read_text(encoding="utf-8"), formatter_ctx_fix)
135
136 assert changed is True
137 assert code_content in new_text
138
139
140def test_header_dry_run_no_modify(temp_project_root: Path, formatter_ctx: FormatterContext):
141 """Test that dry-run mode doesn't modify files."""
142 test_file = temp_project_root / "test_dryrun.py"
143 original_content = "# Missing header\nprint('hello')\n"
144 test_file.write_text(original_content, encoding="utf-8")
145
146 changed, _, messages = fix_header_block(test_file, original_content, formatter_ctx)
147
148 assert changed is True # Changed is detected
149 assert test_file.read_text(encoding="utf-8") == original_content # But file not modified
150
151
152def test_header_correct_no_change(temp_project_root: Path, formatter_ctx_fix: FormatterContext):
153 """Test that correct headers are not modified."""
154 test_file = temp_project_root / "test_correct.py"
155 correct_content = (
156 "#!/usr/bin/env python3\n"
157 "# -*- coding: utf-8 -*-\n"
158 "# test_correct.py\n"
159 "\n"
160 "print('hello')\n"
161 )
162 test_file.write_text(correct_content, encoding="utf-8")
163
164 changed, _, messages = fix_header_block(test_file, correct_content, formatter_ctx_fix)
165
166 assert changed is False
167 assert len(messages) == 0
test_fix_missing_encoding(Path temp_project_root, FormatterContext formatter_ctx_fix)
test_fix_wrong_path_header(Path temp_project_root, FormatterContext formatter_ctx_fix)
test_header_archives_original(Path temp_project_root, FormatterContext formatter_ctx_fix)
test_fix_missing_shebang(Path temp_project_root, FormatterContext formatter_ctx_fix)
test_header_preserves_code(Path temp_project_root, FormatterContext formatter_ctx_fix)
test_header_correct_no_change(Path temp_project_root, FormatterContext formatter_ctx_fix)
test_header_dry_run_no_modify(Path temp_project_root, FormatterContext formatter_ctx)