Skip to content

Commit e3920e2

Browse files
committed
adds unit tests for utils.py
1 parent 5a9a4c6 commit e3920e2

File tree

1 file changed

+253
-0
lines changed

1 file changed

+253
-0
lines changed
Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
# -*- coding: utf-8 -*-
2+
# Copyright 2025 Google LLC
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
"""Tests for utils.py."""
17+
18+
import pytest
19+
from unittest.mock import Mock, patch
20+
21+
from scripts.microgenerator import utils
22+
23+
24+
def test_load_resource_success():
25+
"""Tests that _load_resource returns the loader's result on success."""
26+
loader_func = Mock(return_value="Success")
27+
result = utils._load_resource(
28+
loader_func=loader_func,
29+
path="/fake/path",
30+
not_found_exc=FileNotFoundError,
31+
parse_exc=ValueError,
32+
resource_type_name="Fake Resource",
33+
)
34+
assert result == "Success"
35+
loader_func.assert_called_once()
36+
37+
38+
def test_load_resource_not_found(capsys):
39+
"""Tests that _load_resource exits on not_found_exc."""
40+
loader_func = Mock(side_effect=FileNotFoundError)
41+
with pytest.raises(SystemExit) as excinfo:
42+
utils._load_resource(
43+
loader_func=loader_func,
44+
path="/fake/path",
45+
not_found_exc=FileNotFoundError,
46+
parse_exc=ValueError,
47+
resource_type_name="Fake Resource",
48+
)
49+
assert excinfo.value.code == 1
50+
captured = capsys.readouterr()
51+
assert "Error: Fake Resource '/fake/path' not found." in captured.err
52+
53+
54+
def test_load_resource_parse_error(capsys):
55+
"""Tests that _load_resource exits on parse_exc."""
56+
error = ValueError("Invalid format")
57+
loader_func = Mock(side_effect=error)
58+
with pytest.raises(SystemExit) as excinfo:
59+
utils._load_resource(
60+
loader_func=loader_func,
61+
path="/fake/path",
62+
not_found_exc=FileNotFoundError,
63+
parse_exc=ValueError,
64+
resource_type_name="Fake Resource",
65+
)
66+
assert excinfo.value.code == 1
67+
captured = capsys.readouterr()
68+
assert (
69+
"Error: Could not load fake resource from '/fake/path': Invalid format"
70+
in captured.err
71+
)
72+
73+
74+
def test_load_template_success(tmp_path):
75+
"""Tests that load_template successfully loads a Jinja2 template."""
76+
template_dir = tmp_path / "templates"
77+
template_dir.mkdir()
78+
template_path = template_dir / "test.j2"
79+
template_path.write_text("Hello, {{ name }}!")
80+
81+
template = utils.load_template(str(template_path))
82+
assert template.render(name="World") == "Hello, World!"
83+
84+
85+
def test_load_template_not_found(capsys):
86+
"""Tests that load_template exits when the template is not found."""
87+
with pytest.raises(SystemExit) as excinfo:
88+
utils.load_template("/non/existent/path.j2")
89+
assert excinfo.value.code == 1
90+
captured = capsys.readouterr()
91+
assert "Error: Template file '/non/existent/path.j2' not found." in captured.err
92+
93+
94+
def test_load_template_parse_error(tmp_path, capsys):
95+
"""Tests that load_template exits on a template syntax error."""
96+
template_dir = tmp_path / "templates"
97+
template_dir.mkdir()
98+
template_path = template_dir / "test.j2"
99+
template_path.write_text("Hello, {{ name }!") # Malformed template
100+
101+
with pytest.raises(SystemExit) as excinfo:
102+
utils.load_template(str(template_path))
103+
assert excinfo.value.code == 1
104+
captured = capsys.readouterr()
105+
assert "Could not load template file" in captured.err
106+
107+
108+
def test_load_config_success(tmp_path):
109+
"""Tests that load_config successfully loads a YAML file."""
110+
config_dir = tmp_path / "configs"
111+
config_dir.mkdir()
112+
config_path = config_dir / "config.yaml"
113+
config_path.write_text("key: value")
114+
115+
config = utils.load_config(str(config_path))
116+
assert config == {"key": "value"}
117+
118+
119+
def test_load_config_not_found(capsys):
120+
"""Tests that load_config exits when the config file is not
121+
found."""
122+
with pytest.raises(SystemExit) as excinfo:
123+
utils.load_config("/non/existent/path.yaml")
124+
assert excinfo.value.code == 1
125+
captured = capsys.readouterr()
126+
assert (
127+
"Error: Configuration file '/non/existent/path.yaml' not found." in captured.err
128+
)
129+
130+
131+
def test_load_config_parse_error(tmp_path, capsys):
132+
"""Tests that load_config exits on a YAML syntax error."""
133+
config_dir = tmp_path / "configs"
134+
config_dir.mkdir()
135+
config_path = config_dir / "config.yaml"
136+
config_path.write_text("key: value:") # Malformed YAML
137+
138+
with pytest.raises(SystemExit) as excinfo:
139+
utils.load_config(str(config_path))
140+
assert excinfo.value.code == 1
141+
captured = capsys.readouterr()
142+
assert "Could not load configuration file" in captured.err
143+
144+
145+
def test_walk_codebase_finds_py_files(tmp_path):
146+
"""Tests that walk_codebase finds all .py files."""
147+
# Create a directory structure
148+
(tmp_path / "a").mkdir()
149+
(tmp_path / "b").mkdir()
150+
(tmp_path / "a" / "c").mkdir()
151+
152+
# Create some files
153+
(tmp_path / "a" / "file1.py").touch()
154+
(tmp_path / "a" / "c" / "file2.py").touch()
155+
(tmp_path / "b" / "file3.py").touch()
156+
(tmp_path / "a" / "file.txt").touch() # Should be ignored
157+
(tmp_path / "b" / "script").touch() # Should be ignored
158+
159+
result = sorted(list(utils.walk_codebase(str(tmp_path))))
160+
161+
expected = sorted(
162+
[
163+
str(tmp_path / "a" / "file1.py"),
164+
str(tmp_path / "a" / "c" / "file2.py"),
165+
str(tmp_path / "b" / "file3.py"),
166+
]
167+
)
168+
169+
assert result == expected
170+
171+
172+
def test_walk_codebase_no_py_files(tmp_path):
173+
"""Tests that walk_codebase handles directories with no .py files."""
174+
(tmp_path / "a").mkdir()
175+
(tmp_path / "a" / "file.txt").touch()
176+
(tmp_path / "b").mkdir()
177+
178+
result = list(utils.walk_codebase(str(tmp_path)))
179+
assert result == []
180+
181+
182+
def test_walk_codebase_empty_directory(tmp_path):
183+
"""Tests that walk_codebase handles an empty directory."""
184+
result = list(utils.walk_codebase(str(tmp_path)))
185+
assert result == []
186+
187+
188+
def test_walk_codebase_non_existent_path():
189+
"""Tests that walk_codebase handles a non-existent path gracefully."""
190+
result = list(utils.walk_codebase("/non/existent/path"))
191+
assert result == []
192+
193+
194+
def test_walk_codebase_with_file_path(tmp_path):
195+
"""Tests that walk_codebase handles being passed a file path."""
196+
file_path = tmp_path / "file.py"
197+
file_path.touch()
198+
# os.walk on a file yields nothing, so this should be empty.
199+
result = list(utils.walk_codebase(str(file_path)))
200+
assert result == []
201+
202+
203+
def test_write_code_to_file_creates_directory(tmp_path):
204+
"""Tests that write_code_to_file creates the directory if it doesn't exist."""
205+
output_dir = tmp_path / "new_dir"
206+
output_path = output_dir / "test_file.py"
207+
content = "import this"
208+
209+
assert not output_dir.exists()
210+
211+
utils.write_code_to_file(str(output_path), content)
212+
213+
assert output_dir.is_dir()
214+
assert output_path.read_text() == content
215+
216+
217+
def test_write_code_to_file_existing_directory(tmp_path):
218+
"""Tests that write_code_to_file works when the directory already exists."""
219+
output_path = tmp_path / "test_file.py"
220+
content = "import that"
221+
222+
utils.write_code_to_file(str(output_path), content)
223+
224+
assert output_path.read_text() == content
225+
226+
227+
def test_write_code_to_file_no_directory(tmp_path, monkeypatch):
228+
"""Tests that write_code_to_file works for the current directory."""
229+
monkeypatch.chdir(tmp_path)
230+
output_path = "test_file.py"
231+
content = "import the_other"
232+
233+
utils.write_code_to_file(output_path, content)
234+
235+
assert (tmp_path / output_path).read_text() == content
236+
237+
238+
@patch("os.path.isdir", return_value=False)
239+
@patch("os.makedirs")
240+
def test_write_code_to_file_dir_creation_fails(
241+
mock_makedirs, mock_isdir, tmp_path, capsys
242+
):
243+
"""Tests that write_code_to_file exits if directory creation fails."""
244+
output_path = tmp_path / "new_dir" / "test_file.py"
245+
content = "import this"
246+
247+
with pytest.raises(SystemExit) as excinfo:
248+
utils.write_code_to_file(str(output_path), content)
249+
250+
assert excinfo.value.code == 1
251+
captured = capsys.readouterr()
252+
assert "Error: Output directory was not created." in captured.err
253+
mock_makedirs.assert_called_once()

0 commit comments

Comments
 (0)