Skip to content

Commit 8b8adc8

Browse files
Copilotlachlangrose
andcommitted
Add unit tests for grid export functionality
Co-authored-by: lachlangrose <7371904+lachlangrose@users.noreply.github.com>
1 parent 3a1cd5a commit 8b8adc8

File tree

1 file changed

+145
-0
lines changed

1 file changed

+145
-0
lines changed

tests/unit/test_grid_export.py

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
"""Unit tests for grid export functionality."""
2+
3+
import tempfile
4+
from pathlib import Path
5+
from unittest.mock import MagicMock
6+
7+
import numpy as np
8+
import pytest
9+
10+
11+
def test_export_grid_ascii_basic():
12+
"""Test ASCII export of a simple grid with scalar data."""
13+
# Create a mock mesh object that simulates a PyVista UniformGrid
14+
mock_mesh = MagicMock()
15+
mock_mesh.n_cells = 8
16+
17+
# Mock cell centers
18+
mock_cell_centers = MagicMock()
19+
mock_cell_centers.points = np.array([
20+
[0.5, 0.5, 0.5],
21+
[1.5, 0.5, 0.5],
22+
[0.5, 1.5, 0.5],
23+
[1.5, 1.5, 0.5],
24+
[0.5, 0.5, 1.5],
25+
[1.5, 0.5, 1.5],
26+
[0.5, 1.5, 1.5],
27+
[1.5, 1.5, 1.5],
28+
])
29+
mock_mesh.cell_centers.return_value = mock_cell_centers
30+
31+
# Mock scalar data
32+
mock_mesh.active_scalars_name = "scalar_field"
33+
mock_mesh.cell_data = {
34+
"scalar_field": np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0])
35+
}
36+
37+
# Create a temporary file for export
38+
with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as f:
39+
temp_path = f.name
40+
41+
try:
42+
# Import the ObjectListWidget to get the export method
43+
# We'll test the export method in isolation
44+
from loopstructural.gui.visualisation.object_list_widget import ObjectListWidget
45+
46+
# Create a minimal instance (viewer and properties_widget can be None for this test)
47+
widget = ObjectListWidget(viewer=MagicMock(), properties_widget=None)
48+
49+
# Call the export method
50+
widget._export_grid_ascii(mock_mesh, temp_path, "test_grid")
51+
52+
# Read the exported file
53+
with open(temp_path, 'r') as f:
54+
lines = f.readlines()
55+
56+
# Verify header
57+
assert lines[0].strip() == "# ASCII Grid Export: test_grid"
58+
assert lines[1].strip() == "# Format: x y z value"
59+
assert lines[2].strip() == "# Number of cells: 8"
60+
assert lines[3].strip() == "# Scalar field: scalar_field"
61+
assert lines[4].strip() == "#"
62+
63+
# Verify data lines
64+
data_lines = lines[5:]
65+
assert len(data_lines) == 8
66+
67+
# Verify first data line
68+
first_line = data_lines[0].strip().split()
69+
assert len(first_line) == 4
70+
assert float(first_line[0]) == pytest.approx(0.5, abs=1e-5)
71+
assert float(first_line[1]) == pytest.approx(0.5, abs=1e-5)
72+
assert float(first_line[2]) == pytest.approx(0.5, abs=1e-5)
73+
assert float(first_line[3]) == pytest.approx(1.0, abs=1e-5)
74+
75+
finally:
76+
# Clean up
77+
Path(temp_path).unlink(missing_ok=True)
78+
79+
80+
def test_export_grid_ascii_no_scalars():
81+
"""Test ASCII export when grid has no scalar data."""
82+
# Create a mock mesh without scalar data
83+
mock_mesh = MagicMock()
84+
mock_mesh.n_cells = 4
85+
86+
mock_cell_centers = MagicMock()
87+
mock_cell_centers.points = np.array([
88+
[0.5, 0.5, 0.5],
89+
[1.5, 0.5, 0.5],
90+
[0.5, 1.5, 0.5],
91+
[1.5, 1.5, 0.5],
92+
])
93+
mock_mesh.cell_centers.return_value = mock_cell_centers
94+
95+
# No scalar data
96+
mock_mesh.active_scalars_name = None
97+
mock_mesh.cell_data = {}
98+
99+
with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as f:
100+
temp_path = f.name
101+
102+
try:
103+
from loopstructural.gui.visualisation.object_list_widget import ObjectListWidget
104+
105+
widget = ObjectListWidget(viewer=MagicMock(), properties_widget=None)
106+
widget._export_grid_ascii(mock_mesh, temp_path, "test_grid_no_scalars")
107+
108+
with open(temp_path, 'r') as f:
109+
lines = f.readlines()
110+
111+
# Should still create file with zeros
112+
assert "# ASCII Grid Export: test_grid_no_scalars" in lines[0]
113+
assert len(lines) >= 9 # Header + 4 data lines
114+
115+
# Verify that values are zero
116+
data_lines = lines[5:]
117+
for line in data_lines:
118+
if line.strip():
119+
parts = line.strip().split()
120+
if len(parts) == 4:
121+
value = float(parts[3])
122+
assert value == pytest.approx(0.0, abs=1e-5)
123+
124+
finally:
125+
Path(temp_path).unlink(missing_ok=True)
126+
127+
128+
def test_mesh_type_detection():
129+
"""Test that grid mesh types are correctly detected."""
130+
test_cases = [
131+
("UniformGrid", True),
132+
("ImageData", True),
133+
("StructuredGrid", True),
134+
("RectilinearGrid", True),
135+
("PolyData", False),
136+
("UnstructuredGrid", False),
137+
]
138+
139+
for mesh_type, expected_is_grid in test_cases:
140+
mock_mesh = MagicMock()
141+
mock_mesh.__class__.__name__ = mesh_type
142+
143+
is_grid = type(mock_mesh).__name__ in ['UniformGrid', 'ImageData', 'StructuredGrid', 'RectilinearGrid']
144+
145+
assert is_grid == expected_is_grid, f"Failed for mesh type: {mesh_type}"

0 commit comments

Comments
 (0)