Skip to content

Commit 96d0e05

Browse files
committed
Increase test coverage
1 parent 77606e0 commit 96d0e05

File tree

2 files changed

+212
-0
lines changed

2 files changed

+212
-0
lines changed

tests/test_cli.py

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
import argparse
2+
import os
3+
from unittest.mock import patch, MagicMock
4+
5+
import pytest
6+
import pyvips
7+
8+
from image_slicer.cli import main
9+
10+
11+
@pytest.fixture(scope="module")
12+
def test_image_path(tmpdir_factory):
13+
"""
14+
Creates a temporary black PNG image for testing.
15+
"""
16+
path = str(tmpdir_factory.mktemp("data").join("test_image.png"))
17+
image = pyvips.Image.black(100, 85, bands=1)
18+
image.write_to_file(path)
19+
return path
20+
21+
22+
def test_main_with_grid_arguments(test_image_path, tmp_path):
23+
"""
24+
Tests the CLI main function with grid arguments.
25+
"""
26+
output_dir = str(tmp_path / "output_cli_grid")
27+
28+
with patch('sys.argv', ['imslice', test_image_path, output_dir, '--grid', '2', '3']):
29+
main()
30+
31+
files = os.listdir(output_dir)
32+
assert len(files) == 6 # 2*3 = 6 tiles
33+
34+
35+
def test_main_with_number_of_tiles_argument(test_image_path, tmp_path):
36+
"""
37+
Tests the CLI main function with number of tiles argument.
38+
"""
39+
output_dir = str(tmp_path / "output_cli_tiles")
40+
41+
with patch('sys.argv', ['imslice', test_image_path, output_dir, '--number-of-tiles', '4']):
42+
main()
43+
44+
files = os.listdir(output_dir)
45+
assert len(files) == 4
46+
47+
48+
def test_main_with_tile_size_arguments(test_image_path, tmp_path):
49+
"""
50+
Tests the CLI main function with tile size arguments.
51+
"""
52+
output_dir = str(tmp_path / "output_cli_size")
53+
54+
with patch('sys.argv', ['imslice', test_image_path, output_dir, '--tile-size', '50', '40']):
55+
main()
56+
57+
files = os.listdir(output_dir)
58+
# 100/50 = 2 cols, 85/40 = 3 rows (rounded up) = 2*3 = 6 tiles
59+
assert len(files) == 6
60+
61+
62+
def test_main_with_custom_format(test_image_path, tmp_path):
63+
"""
64+
Tests the CLI main function with custom naming format.
65+
"""
66+
output_dir = str(tmp_path / "output_cli_format")
67+
68+
with patch('sys.argv', ['imslice', test_image_path, output_dir, '--grid', '2', '2',
69+
'--format', 'custom_{row}_{col}.jpg']):
70+
main()
71+
72+
files = os.listdir(output_dir)
73+
assert 'custom_0_0.jpg' in files
74+
assert 'custom_1_1.jpg' in files
75+
assert len(files) == 4
76+
77+
78+
def test_main_with_short_arguments(test_image_path, tmp_path):
79+
"""
80+
Tests the CLI main function with short argument forms.
81+
"""
82+
output_dir = str(tmp_path / "output_cli_short")
83+
84+
with patch('sys.argv', ['imslice', test_image_path, output_dir, '-g', '3', '2']):
85+
main()
86+
87+
files = os.listdir(output_dir)
88+
assert len(files) == 6 # 3*2 = 6 tiles
89+
90+
91+
def test_main_number_of_tiles_short_form(test_image_path, tmp_path):
92+
"""
93+
Tests the CLI main function with short form of number-of-tiles.
94+
"""
95+
output_dir = str(tmp_path / "output_cli_n")
96+
97+
with patch('sys.argv', ['imslice', test_image_path, output_dir, '-n', '9']):
98+
main()
99+
100+
files = os.listdir(output_dir)
101+
assert len(files) == 9
102+
103+
104+
def test_main_tile_size_short_form(test_image_path, tmp_path):
105+
"""
106+
Tests the CLI main function with short form of tile-size.
107+
"""
108+
output_dir = str(tmp_path / "output_cli_t")
109+
110+
with patch('sys.argv', ['imslice', test_image_path, output_dir, '-t', '25', '30']):
111+
main()
112+
113+
files = os.listdir(output_dir)
114+
# 100/25 = 4 cols, 85/30 = 3 rows (rounded up) = 4*3 = 12 tiles
115+
assert len(files) == 12
116+
117+
118+
def test_main_custom_format_short_form(test_image_path, tmp_path):
119+
"""
120+
Tests the CLI main function with short form of format.
121+
"""
122+
output_dir = str(tmp_path / "output_cli_f")
123+
124+
with patch('sys.argv', ['imslice', test_image_path, output_dir, '-g', '2', '2',
125+
'-f', 'piece_{row}_{col}.png']):
126+
main()
127+
128+
files = os.listdir(output_dir)
129+
assert 'piece_0_0.png' in files
130+
assert 'piece_1_1.png' in files
131+
132+
133+
def test_main_missing_required_argument():
134+
"""
135+
Tests that the CLI raises SystemExit when required mutually exclusive group is missing.
136+
"""
137+
with patch('sys.argv', ['imslice', 'source.png', 'output_dir']):
138+
with pytest.raises(SystemExit):
139+
main()
140+
141+
142+
def test_main_conflicting_arguments():
143+
"""
144+
Tests that the CLI raises SystemExit when mutually exclusive arguments are provided.
145+
"""
146+
with patch('sys.argv', ['imslice', 'source.png', 'output_dir',
147+
'--grid', '2', '2', '--number-of-tiles', '4']):
148+
with pytest.raises(SystemExit):
149+
main()
150+
151+
152+
def test_main_invalid_image_path(tmp_path):
153+
"""
154+
Tests that the CLI handles invalid image paths gracefully.
155+
"""
156+
output_dir = str(tmp_path / "output_cli_invalid")
157+
158+
with patch('sys.argv', ['imslice', 'nonexistent.png', output_dir, '--grid', '2', '2']):
159+
with pytest.raises(pyvips.Error):
160+
main()
161+
162+
163+
def test_main_module_execution(test_image_path, tmp_path):
164+
"""
165+
Tests the __main__ execution path of the CLI module.
166+
"""
167+
import subprocess
168+
import sys
169+
170+
output_dir = str(tmp_path / "output_main_module")
171+
172+
# Execute the CLI module directly via Python
173+
result = subprocess.run([
174+
sys.executable, '-m', 'image_slicer.cli',
175+
test_image_path, output_dir, '--grid', '2', '2'
176+
], cwd='/Users/sam/image_slicer', env={'PYTHONPATH': 'src'},
177+
capture_output=True, text=True)
178+
179+
# Check that it executed successfully
180+
assert result.returncode == 0
181+
182+
# Check that files were created
183+
files = os.listdir(output_dir)
184+
assert len(files) == 4 # 2*2 = 4 tiles

tests/test_slicer.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,12 @@ def test_get_grid_from_tiles_logic():
103103
"""
104104
Tests the internal logic for calculating grid dimensions from tile count.
105105
"""
106+
# Test small numbers (edge cases)
107+
assert _get_grid_from_tiles(1) == (1, 1)
108+
assert _get_grid_from_tiles(2) == (1, 2)
109+
assert _get_grid_from_tiles(3) == (1, 3)
110+
111+
# Test larger numbers
106112
assert _get_grid_from_tiles(4) == (2, 2)
107113
assert _get_grid_from_tiles(6) == (2, 3)
108114
assert _get_grid_from_tiles(8) == (2, 4)
@@ -220,3 +226,25 @@ def test_naming_format(test_image_path, tmp_path):
220226
assert "slice_row0_col0.jpg" in files
221227
assert "slice_row1_col1.jpg" in files
222228
assert len(files) == 4
229+
230+
231+
def test_calculate_tile_dimensions_error_case(test_image_path):
232+
"""
233+
Tests the error case in _calculate_tile_dimensions when insufficient parameters are provided.
234+
"""
235+
slicer = ImageSlicer(test_image_path)
236+
237+
# This should raise an error since neither tile_width/height nor cols/rows nor number_of_tiles are provided
238+
with pytest.raises(ValueError, match="You must specify either"):
239+
slicer._calculate_tile_dimensions()
240+
241+
242+
def test_generate_tiles_without_criteria_raises_error(test_image_path):
243+
"""
244+
Tests that calling generate_tiles without any slicing criteria raises an error.
245+
"""
246+
slicer = ImageSlicer(test_image_path)
247+
248+
# This should match the error on line 195
249+
with pytest.raises(ValueError, match="Slicing criteria not provided"):
250+
list(slicer.generate_tiles())

0 commit comments

Comments
 (0)