@@ -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