3535 "large_time_stamps" ,
3636]
3737
38+ # Inverted range is intentionally separate from INVALID_META_CASES -
39+ # None/NaN/inf are caught per-device before being added to self.devices,
40+ # whereas start > end is only caught after all devices are loaded.
3841INVALID_META_CASES = [
39- {"start_time" : None , "end_time" : None },
40- {"start_time" : None , "end_time" : 10.0 },
41- {"start_time" : 0.0 , "end_time" : None },
42- {"start_time" : float ("inf" ), "end_time" : 10.0 },
43- {"start_time" : 0.0 , "end_time" : float ("inf" )},
44- {"start_time" : float ("-inf" ), "end_time" : 10.0 },
45- {"start_time" : 0.0 , "end_time" : float ("-inf" )},
46- {"start_time" : float ("nan" ), "end_time" : 10.0 },
47- {"start_time" : 0.0 , "end_time" : float ("nan" )},
42+ {"start_time" : None , "end_time" : None }, # Both missing
43+ {"start_time" : None , "end_time" : 10.0 }, # Missing start_time
44+ {"start_time" : 0.0 , "end_time" : None }, # Missing end_time
45+ {"start_time" : float ("inf" ), "end_time" : 10.0 }, # Infinite start_time
46+ {"start_time" : 0.0 , "end_time" : float ("inf" )}, # Infinite end_time
47+ {"start_time" : float ("-inf" ), "end_time" : 10.0 }, # Negative Infinite start_time
48+ {"start_time" : 0.0 , "end_time" : float ("-inf" )}, # Negative Infinite end_time
49+ {"start_time" : float ("nan" ), "end_time" : 10.0 }, # NaN start_time
50+ {"start_time" : 0.0 , "end_time" : float ("nan" )}, # NaN end_time
4851]
4952
5053INVALID_META_IDS = [
@@ -89,10 +92,14 @@ def test_experiment_initialization_and_device_loading(tmp_path, mock_interpolato
8992 "eye_tracker" : {"interpolation" : mock_interpolator },
9093 }
9194 exp = Experiment (root_folder = str (tmp_path ), modality_config = config )
92- assert "screen" in exp .devices
93- assert "eye_tracker" in exp .devices
94- assert "ignored_device" not in exp .devices
95- assert set (exp .device_names ) == {"screen" , "eye_tracker" }
95+ assert "screen" in exp .devices , "Expected 'screen' in experiment devices"
96+ assert "eye_tracker" in exp .devices , "Expected 'eye_tracker' in experiment devices"
97+ assert "ignored_device" not in exp .devices , (
98+ "Expected 'ignored_device' to be excluded"
99+ )
100+ assert set (exp .device_names ) == {"screen" , "eye_tracker" }, (
101+ f"Expected {{'screen', 'eye_tracker'}}, got { set (exp .device_names )} "
102+ )
96103
97104
98105def test_experiment_interpolate_routing (tmp_path , mock_interpolator ):
@@ -105,10 +112,20 @@ def test_experiment_interpolate_routing(tmp_path, mock_interpolator):
105112 mock_interpolator .interpolate .assert_called_once_with (
106113 test_times , return_valid = False
107114 )
108- np .testing .assert_array_equal (res , np .array ([1 , 2 , 3 ]))
115+ np .testing .assert_array_equal (
116+ res ,
117+ np .array ([1 , 2 , 3 ]),
118+ err_msg = "Interpolated result does not match mock output" ,
119+ )
109120 res_dict = exp .interpolate (test_times , device = None )
110- assert isinstance (res_dict , dict )
111- np .testing .assert_array_equal (res_dict ["screen" ], np .array ([1 , 2 , 3 ]))
121+ assert isinstance (res_dict , dict ), (
122+ f"Expected dict return for device=None, got { type (res_dict )} "
123+ )
124+ np .testing .assert_array_equal (
125+ res_dict ["screen" ],
126+ np .array ([1 , 2 , 3 ]),
127+ err_msg = "Interpolated dict result does not match mock output" ,
128+ )
112129
113130
114131@pytest .mark .parametrize (
@@ -136,7 +153,9 @@ def test_get_valid_range_all_devices(tmp_path, device_name, start_t, end_t):
136153 root_folder = str (experiment_path ), modality_config = config
137154 )
138155 valid_range = experiment .get_valid_range (device_name )
139- assert valid_range == (start_t , end_t )
156+ assert valid_range == (start_t , end_t ), (
157+ f"Expected valid range { (start_t , end_t )} for { device_name } , got { valid_range } "
158+ )
140159
141160
142161def test_get_valid_range_raises_for_invalid_device (tmp_path ):
@@ -259,8 +278,12 @@ def test_experiment_start_end_time_reflects_union(
259278 )
260279
261280 # Removed pytest.approx here
262- assert experiment .start_time == expected_start
263- assert experiment .end_time == expected_end
281+ assert experiment .start_time == (expected_start ), (
282+ f"Expected start_time={ expected_start } , got { experiment .start_time } "
283+ )
284+ assert experiment .end_time == (expected_end ), (
285+ f"Expected end_time={ expected_end } , got { experiment .end_time } "
286+ )
264287
265288
266289@pytest .mark .parametrize ("override_meta" , INVALID_META_CASES , ids = INVALID_META_IDS )
@@ -270,7 +293,7 @@ def test_experiment_invalid_metadata(tmp_path, override_meta):
270293 ) as experiment_path :
271294 # Explicitly corrupt the generated metadata file
272295 meta_file = experiment_path / "device_0" / "meta.yml"
273- with open (meta_file , "r" ) as f :
296+ with open (meta_file ) as f :
274297 meta = yaml .safe_load (f )
275298 meta .update (override_meta )
276299 with open (meta_file , "w" ) as f :
@@ -286,10 +309,14 @@ def test_experiment_invalid_metadata(tmp_path, override_meta):
286309
287310@pytest .mark .parametrize ("override_meta" , INVALID_META_CASES , ids = INVALID_META_IDS )
288311def test_experiment_skips_invalid_devices (tmp_path , override_meta , caplog ):
289- start_val , duration_val = (
290- np .random .lognormal (0.0 , 1.0 ),
291- np .random .lognormal (0.0 , 1.0 ),
292- )
312+ """
313+ Experiment should skip devices with invalid start_time or end_time and
314+ log a warning, but still initialize successfully if at least one valid
315+ device is present. The experiment time range should reflect only the
316+ valid device.
317+ """
318+ start_val = np .random .lognormal (mean = 0.0 , sigma = 1.0 ) # Strictly positive float
319+ duration_val = np .random .lognormal (mean = 0.0 , sigma = 1.0 )
293320 end_val = start_val + duration_val
294321
295322 devices_kwargs = [
@@ -306,7 +333,7 @@ def test_experiment_skips_invalid_devices(tmp_path, override_meta, caplog):
306333
307334 # Explicitly corrupt the metadata file for the invalid device
308335 meta_file = experiment_path / "invalid_device" / "meta.yml"
309- with open (meta_file , "r" ) as f :
336+ with open (meta_file ) as f :
310337 meta = yaml .safe_load (f )
311338 meta .update (override_meta )
312339 with open (meta_file , "w" ) as f :
@@ -319,8 +346,20 @@ def test_experiment_skips_invalid_devices(tmp_path, override_meta, caplog):
319346 root_folder = str (experiment_path ), modality_config = config
320347 )
321348
322- assert "valid_device" in experiment .devices
323- assert "invalid_device" not in experiment .devices
349+ assert "valid_device" in experiment .devices , (
350+ "Expected 'valid_device' to be initialized"
351+ )
352+ assert "invalid_device" not in experiment .devices , (
353+ "Expected 'invalid_device' to be skipped"
354+ )
355+
324356 # Removed pytest.approx here
325- assert experiment .start_time == start_val
326- assert experiment .end_time == end_val
357+ assert experiment .start_time == (start_val ), (
358+ f"Expected start_time={ start_val } , got { experiment .start_time } "
359+ )
360+ assert experiment .end_time == (end_val ), (
361+ f"Expected end_time={ end_val } , got { experiment .end_time } "
362+ )
363+ assert any ("invalid_device" in message for message in caplog .messages ), (
364+ "Expected warning about invalid_device was skipped"
365+ )
0 commit comments