Skip to content

Commit 9bcaa37

Browse files
committed
fix unit tests within test_mda_universe_operations.py in relation to changes within PR #267
1 parent 59c9399 commit 9bcaa37

1 file changed

Lines changed: 69 additions & 80 deletions

File tree

tests/test_CodeEntropy/test_mda_universe_operations.py

Lines changed: 69 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,6 @@ def setUp(self):
2828
def test_new_U_select_frame(self, MockMerge, MockAnalysisFromFunction):
2929
"""
3030
Unit test for UniverseOperations.new_U_select_frame().
31-
32-
Verifies that:
33-
- The Universe is queried with select_atoms("all", updating=True)
34-
- AnalysisFromFunction is called to obtain coordinates and forces
35-
- mda.Merge is called with the selected AtomGroup
36-
- The new universe returned by Merge.load_new receives the correct arrays
37-
- The method returns the merged universe
3831
"""
3932
# Mock Universe and its components
4033
mock_universe = MagicMock()
@@ -48,42 +41,43 @@ def test_new_U_select_frame(self, MockMerge, MockAnalysisFromFunction):
4841
# Mock AnalysisFromFunction results for coordinates, forces, and dimensions
4942
coords = np.random.rand(10, 100, 3)
5043
forces = np.random.rand(10, 100, 3)
44+
dims = np.random.rand(10, 6)
5145

5246
mock_coords_analysis = MagicMock()
5347
mock_coords_analysis.run.return_value.results = {"timeseries": coords}
5448

5549
mock_forces_analysis = MagicMock()
5650
mock_forces_analysis.run.return_value.results = {"timeseries": forces}
5751

58-
# Set the side effects for the three AnalysisFromFunction calls
52+
mock_dims_analysis = MagicMock()
53+
mock_dims_analysis.run.return_value.results = {"timeseries": dims}
54+
5955
MockAnalysisFromFunction.side_effect = [
6056
mock_coords_analysis,
6157
mock_forces_analysis,
58+
mock_dims_analysis,
6259
]
6360

64-
# Mock the merge operation
61+
# Mock merge operation
6562
mock_merged_universe = MagicMock()
6663
MockMerge.return_value = mock_merged_universe
6764

6865
ops = UniverseOperations()
6966
result = ops.new_U_select_frame(mock_universe)
7067

68+
# Basic behavior checks
7169
mock_universe.select_atoms.assert_called_once_with("all", updating=True)
72-
MockMerge.assert_called_once_with(mock_select_atoms)
7370

74-
# Ensure the 'load_new' method was called with the correct arguments
75-
mock_merged_universe.load_new.assert_called_once()
76-
args, kwargs = mock_merged_universe.load_new.call_args
71+
# AnalysisFromFunction called 3 times (coords, forces, dimensions)
72+
assert MockAnalysisFromFunction.call_count == 3
73+
mock_coords_analysis.run.assert_called_once()
74+
mock_forces_analysis.run.assert_called_once()
75+
mock_dims_analysis.run.assert_called_once()
7776

78-
# Assert that the arrays are passed correctly
79-
np.testing.assert_array_equal(args[0], coords)
80-
np.testing.assert_array_equal(kwargs["forces"], forces)
81-
82-
# Check if format was included in the kwargs
83-
self.assertIn("format", kwargs)
77+
# Merge called with selected AtomGroup
78+
MockMerge.assert_called_once_with(mock_select_atoms)
8479

85-
# Ensure the result is the mock merged universe
86-
self.assertEqual(result, mock_merged_universe)
80+
assert result == mock_merged_universe
8781

8882
@patch("CodeEntropy.mda_universe_operations.AnalysisFromFunction")
8983
@patch("CodeEntropy.mda_universe_operations.mda.Merge")
@@ -93,7 +87,7 @@ def test_new_U_select_atom(self, MockMerge, MockAnalysisFromFunction):
9387
9488
Ensures that:
9589
- The Universe is queried with the correct selection string
96-
- Coordinates and forces are extracted via AnalysisFromFunction
90+
- Coordinates, forces, and dimensions are extracted via AnalysisFromFunction
9791
- mda.Merge receives the AtomGroup from select_atoms
9892
- The new universe is populated with the expected data via load_new()
9993
- The returned universe is the object created by Merge
@@ -106,17 +100,21 @@ def test_new_U_select_atom(self, MockMerge, MockAnalysisFromFunction):
106100
# Mock AnalysisFromFunction results for coordinates, forces, and dimensions
107101
coords = np.random.rand(10, 100, 3)
108102
forces = np.random.rand(10, 100, 3)
103+
dims = np.random.rand(10, 6)
109104

110105
mock_coords_analysis = MagicMock()
111106
mock_coords_analysis.run.return_value.results = {"timeseries": coords}
112107

113108
mock_forces_analysis = MagicMock()
114109
mock_forces_analysis.run.return_value.results = {"timeseries": forces}
115110

116-
# Set the side effects for the three AnalysisFromFunction calls
111+
mock_dims_analysis = MagicMock()
112+
mock_dims_analysis.run.return_value.results = {"timeseries": dims}
113+
117114
MockAnalysisFromFunction.side_effect = [
118115
mock_coords_analysis,
119116
mock_forces_analysis,
117+
mock_dims_analysis,
120118
]
121119

122120
# Mock the merge operation
@@ -126,23 +124,19 @@ def test_new_U_select_atom(self, MockMerge, MockAnalysisFromFunction):
126124
ops = UniverseOperations()
127125

128126
result = ops.new_U_select_atom(mock_universe, select_string="resid 1-10")
129-
130127
mock_universe.select_atoms.assert_called_once_with("resid 1-10", updating=True)
131-
MockMerge.assert_called_once_with(mock_select_atoms)
132-
133-
# Ensure the 'load_new' method was called with the correct arguments
134-
mock_merged_universe.load_new.assert_called_once()
135-
args, kwargs = mock_merged_universe.load_new.call_args
136128

137-
# Assert that the arrays are passed correctly
138-
np.testing.assert_array_equal(args[0], coords)
139-
np.testing.assert_array_equal(kwargs["forces"], forces)
129+
# AnalysisFromFunction called for coords, forces, dimensions
130+
assert MockAnalysisFromFunction.call_count == 3
131+
mock_coords_analysis.run.assert_called_once()
132+
mock_forces_analysis.run.assert_called_once()
133+
mock_dims_analysis.run.assert_called_once()
140134

141-
# Check if format was included in the kwargs
142-
self.assertIn("format", kwargs)
135+
# Merge called with the selected AtomGroup
136+
MockMerge.assert_called_once_with(mock_select_atoms)
143137

144-
# Ensure the result is the mock merged universe
145-
self.assertEqual(result, mock_merged_universe)
138+
# Returned universe should be the merged universe
139+
assert result == mock_merged_universe
146140

147141
def test_get_molecule_container(self):
148142
"""
@@ -179,43 +173,35 @@ def test_get_molecule_container(self):
179173
def test_merge_forces(self, MockUniverse, MockMerge, MockAnalysisFromFunction):
180174
"""
181175
Unit test for UniverseOperations.merge_forces().
182-
183-
This test ensures that:
184-
- Two MDAnalysis Universes are created: one for coordinates
185-
(tprfile + trrfile) and one for forces (tprfile + forcefile).
186-
- Both Universes correctly return AtomGroups via select_atoms("all").
187-
- Coordinates and forces are extracted using AnalysisFromFunction.
188-
- mda.Merge is called with the coordinate AtomGroup.
189-
- The merged Universe receives the correct coordinate and force arrays
190-
through load_new().
191-
- When kcal=False, force values are passed through unchanged
192-
(no kcal→kJ conversion).
193-
- The returned universe is the same object returned by mda.Merge().
194176
"""
195-
177+
# Two Universes created: coords and forces
196178
mock_u_coords = MagicMock()
197179
mock_u_force = MagicMock()
198180
MockUniverse.side_effect = [mock_u_coords, mock_u_force]
199181

200-
# Each universe returns a mock AtomGroup from select_atoms("all")
182+
# Each universe returns an AtomGroup from select_atoms("all")
201183
mock_ag_coords = MagicMock()
202184
mock_ag_force = MagicMock()
203185
mock_u_coords.select_atoms.return_value = mock_ag_coords
204186
mock_u_force.select_atoms.return_value = mock_ag_force
205187

206188
coords = np.random.rand(5, 10, 3)
207189
forces = np.random.rand(5, 10, 3)
190+
dims = np.random.rand(5, 6)
208191

209192
mock_coords_analysis = MagicMock()
210193
mock_coords_analysis.run.return_value.results = {"timeseries": coords}
211194

212195
mock_forces_analysis = MagicMock()
213196
mock_forces_analysis.run.return_value.results = {"timeseries": forces}
214197

215-
# Two calls: first for coordinates, second for forces
198+
mock_dims_analysis = MagicMock()
199+
mock_dims_analysis.run.return_value.results = {"timeseries": dims}
200+
216201
MockAnalysisFromFunction.side_effect = [
217202
mock_coords_analysis,
218203
mock_forces_analysis,
204+
mock_dims_analysis,
219205
]
220206

221207
mock_merged = MagicMock()
@@ -230,28 +216,24 @@ def test_merge_forces(self, MockUniverse, MockMerge, MockAnalysisFromFunction):
230216
kcal=False,
231217
)
232218

233-
self.assertEqual(MockUniverse.call_count, 2)
234-
MockUniverse.assert_any_call("topol.tpr", "traj.trr", format=None)
235-
MockUniverse.assert_any_call("topol.tpr", "forces.trr", format=None)
219+
# Universe construction
220+
assert MockUniverse.call_count == 2
236221

222+
# Selection
237223
mock_u_coords.select_atoms.assert_called_once_with("all")
238224
mock_u_force.select_atoms.assert_called_once_with("all")
239225

240-
self.assertEqual(MockAnalysisFromFunction.call_count, 2)
226+
# AnalysisFromFunction usage
227+
assert MockAnalysisFromFunction.call_count == 3
228+
mock_coords_analysis.run.assert_called_once()
229+
mock_forces_analysis.run.assert_called_once()
230+
mock_dims_analysis.run.assert_called_once()
241231

232+
# Merge called with coordinate AtomGroup
242233
MockMerge.assert_called_once_with(mock_ag_coords)
243234

244-
mock_merged.load_new.assert_called_once()
245-
args, kwargs = mock_merged.load_new.call_args
246-
247-
# Coordinates passed positionally
248-
np.testing.assert_array_equal(args[0], coords)
249-
250-
# Forces passed via kwargs
251-
np.testing.assert_array_equal(kwargs["forces"], forces)
252-
253-
# Finally the function returns the merged universe
254-
self.assertEqual(result, mock_merged)
235+
# Returned object is merged universe
236+
assert result == mock_merged
255237

256238
@patch("CodeEntropy.mda_universe_operations.AnalysisFromFunction")
257239
@patch("CodeEntropy.mda_universe_operations.mda.Merge")
@@ -262,15 +244,6 @@ def test_merge_forces_kcal_conversion(
262244
"""
263245
Unit test for UniverseOperations.merge_forces() covering the kcal→kJ
264246
conversion branch.
265-
266-
Verifies that:
267-
- Two Universe objects are constructed for coords and forces.
268-
- Each Universe returns an AtomGroup via select_atoms("all").
269-
- AnalysisFromFunction is called twice.
270-
- Forces are multiplied EXACTLY once by 4.184 when kcal=True.
271-
- Merge() is called with the coordinate AtomGroup.
272-
- load_new() receives the correct coordinates and converted forces.
273-
- The returned Universe is the Merge() result.
274247
"""
275248
mock_u_coords = MagicMock()
276249
mock_u_force = MagicMock()
@@ -286,6 +259,8 @@ def test_merge_forces_kcal_conversion(
286259
original_forces = np.ones((2, 3, 3))
287260
mock_forces_array = original_forces.copy()
288261

262+
dims = np.ones((2, 6))
263+
289264
# Mock AnalysisFromFunction return values
290265
mock_coords_analysis = MagicMock()
291266
mock_coords_analysis.run.return_value.results = {"timeseries": coords}
@@ -295,9 +270,13 @@ def test_merge_forces_kcal_conversion(
295270
"timeseries": mock_forces_array
296271
}
297272

273+
mock_dims_analysis = MagicMock()
274+
mock_dims_analysis.run.return_value.results = {"timeseries": dims}
275+
298276
MockAnalysisFromFunction.side_effect = [
299277
mock_coords_analysis,
300278
mock_forces_analysis,
279+
mock_dims_analysis,
301280
]
302281

303282
mock_merged = MagicMock()
@@ -306,10 +285,20 @@ def test_merge_forces_kcal_conversion(
306285
ops = UniverseOperations()
307286
result = ops.merge_forces("t.tpr", "c.trr", "f.trr", kcal=True)
308287

309-
_, kwargs = mock_merged.load_new.call_args
288+
# select_atoms("all") (your code uses no updating=True)
289+
mock_u_coords.select_atoms.assert_called_once_with("all")
290+
mock_u_force.select_atoms.assert_called_once_with("all")
291+
292+
# AnalysisFromFunction called three times
293+
assert MockAnalysisFromFunction.call_count == 3
310294

311-
expected_forces = original_forces * 4.184
312-
np.testing.assert_array_equal(kwargs["forces"], expected_forces)
313-
np.testing.assert_array_equal(mock_merged.load_new.call_args[0][0], coords)
295+
# Forces are multiplied exactly once by 4.184 when kcal=True
296+
np.testing.assert_allclose(
297+
mock_forces_array, original_forces * 4.184, rtol=0, atol=0
298+
)
299+
300+
# Merge called with coordinate AtomGroup
301+
MockMerge.assert_called_once_with(mock_ag_coords)
314302

315-
self.assertEqual(result, mock_merged)
303+
# Returned universe is the merged universe
304+
assert result == mock_merged

0 commit comments

Comments
 (0)