Option C Tools
Loading...
Searching...
No Matches
test_integration.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3# tests/tests_formatter/test_integration.py
4
5"""
6Integration tests for the formatter.
7
8Purpose
9-------
10Verify end-to-end formatter behavior with complete projects.
11
12Responsibilities
13----------------
14- Test dry-run mode (no modifications).
15- Test fix mode (applies all fixes).
16- Test JSON output format.
17- Test exclusion list behavior.
18- Test verbose output.
19
20Diagnostics
21-----------
22Domain: TESTS.FORMATTER
23Levels:
24 L2 — test lifecycle
25 L3 — full project processing
26 L4 — output validation and file state verification
27
28Contracts
29---------
30- Dry-run reports changes without modifying files.
31- Fix mode applies all changes and archives originals.
32- JSON output is valid JSON with correct schema.
33- Excluded directories are never processed.
34"""
35
36import pytest
37import json
38import sys
39from pathlib import Path
40from io import StringIO
41
42from oct.formatter.oct_format import run_formatter
43
44
45def test_formatter_processes_project(temp_project_root: Path):
46 """Test that formatter can process an entire project."""
47 # Create test file
48 test_file = temp_project_root / "test.py"
49 test_file.write_text(
50 "# No header\n"
51 "def hello():\n"
52 " pass\n"
53 + "\n".join(["# padding"] * 20),
54 encoding="utf-8"
55 )
56
57 # Run formatter
58 run_formatter(temp_project_root, ["--dry-run"])
59
60
61def test_formatter_dry_run_no_changes(temp_project_root: Path):
62 """Test that dry-run mode doesn't modify files."""
63 test_file = temp_project_root / "test.py"
64 original_content = (
65 "# No header\n"
66 "def hello():\n"
67 " pass\n"
68 + "\n".join(["# padding"] * 20)
69 )
70 test_file.write_text(original_content, encoding="utf-8")
71
72 run_formatter(temp_project_root, ["--dry-run"])
73
74 assert test_file.read_text(encoding="utf-8") == original_content
75
76
77def test_formatter_fix_mode_applies_changes(temp_project_root: Path):
78 """Test that fix mode applies changes and archives originals."""
79 test_file = temp_project_root / "test.py"
80 original_content = (
81 "# No header\n"
82 "def hello():\n"
83 " pass\n"
84 + "\n".join(["# padding"] * 20)
85 )
86 test_file.write_text(original_content, encoding="utf-8")
87
88 run_formatter(temp_project_root, ["--fix"])
89
90 # Verify file was modified
91 new_content = test_file.read_text(encoding="utf-8")
92 assert new_content != original_content
93 assert new_content.startswith("#!/usr/bin/env python3")
94
95 # Verify original was archived
96 archive_dir = test_file.parent / ".formatter_archive"
97 assert archive_dir.exists()
98 backups = list(archive_dir.glob("test.py.*"))
99 assert len(backups) == 1
100
101
102def test_formatter_json_output(temp_project_root: Path, capsys):
103 """Test that JSON output is valid and has correct schema."""
104 test_file = temp_project_root / "test.py"
105 test_file.write_text(
106 "# No header\n"
107 "def hello():\n"
108 " pass\n"
109 + "\n".join(["# padding"] * 20),
110 encoding="utf-8"
111 )
112
113 run_formatter(temp_project_root, ["--dry-run", "--json"])
114
115 captured = capsys.readouterr()
116 output = captured.out
117
118 # Parse JSON
119 data = json.loads(output)
120
121 # Verify schema
122 assert "project" in data
123 assert "oct_version" in data
124 assert "timestamp" in data
125 assert "summary" in data
126 assert "files" in data
127 assert "dry_run" in data
128
129 # Verify summary structure
130 assert "total_files" in data["summary"]
131 assert "total_changed" in data["summary"]
132 assert "fixes" in data["summary"]
133
134
135def test_formatter_verbose_output(temp_project_root: Path, capsys):
136 """Test that verbose mode shows per-file details."""
137 test_file = temp_project_root / "test.py"
138 test_file.write_text(
139 "# No header\n"
140 "def hello():\n"
141 " pass\n"
142 + "\n".join(["# padding"] * 20),
143 encoding="utf-8"
144 )
145
146 run_formatter(temp_project_root, ["--dry-run", "--verbose"])
147
148 captured = capsys.readouterr()
149 output = captured.out
150
151 # Verify detailed output
152 assert "Detailed results:" in output
153 assert "test.py" in output
154
155
156def test_formatter_respects_exclusions(temp_project_root: Path):
157 """Test that excluded directories are not processed."""
158 # Create excluded directory
159 excluded_dir = temp_project_root / ".git"
160 excluded_dir.mkdir()
161 excluded_file = excluded_dir / "test.py"
162 original_content = "# No header\n" + "\n".join(["# padding"] * 20)
163 excluded_file.write_text(original_content, encoding="utf-8")
164
165 run_formatter(temp_project_root, ["--fix"])
166
167 # Verify excluded file was not modified
168 assert excluded_file.read_text(encoding="utf-8") == original_content
169
170
171def test_formatter_handles_syntax_errors(temp_project_root: Path):
172 """Test that formatter handles syntax errors gracefully."""
173 bad_file = temp_project_root / "bad_syntax.py"
174 bad_file.write_text("def foo(:\n pass\n" + "\n".join(["# padding"] * 20), encoding="utf-8")
175
176 # Should not crash
177 run_formatter(temp_project_root, ["--dry-run"])
178
179
180def test_formatter_counts_files_correctly(temp_project_root: Path, capsys):
181 """Test that file counts are accurate."""
182 # Create multiple files
183 for i in range(3):
184 test_file = temp_project_root / f"test{i}.py"
185 test_file.write_text(
186 "# No header\n"
187 + "\n".join(["# padding"] * 20),
188 encoding="utf-8"
189 )
190
191 run_formatter(temp_project_root, ["--dry-run"])
192
193 captured = capsys.readouterr()
194 output = captured.out
195
196 # Verify counts
197 assert "Files processed: 3" in output or "Files processed: 3" in output
test_formatter_dry_run_no_changes(Path temp_project_root)
test_formatter_fix_mode_applies_changes(Path temp_project_root)
test_formatter_handles_syntax_errors(Path temp_project_root)
test_formatter_verbose_output(Path temp_project_root, capsys)
test_formatter_respects_exclusions(Path temp_project_root)
test_formatter_json_output(Path temp_project_root, capsys)
test_formatter_processes_project(Path temp_project_root)
test_formatter_counts_files_correctly(Path temp_project_root, capsys)