1010class TestGetMeasurementConditions :
1111 """Test suite for _get_measurement_conditions function"""
1212
13- def test_with_prepared_values (self ):
14- """Test extracting conditions from measurement with prepared values """
13+ def test_with_initial_as_default (self ):
14+ """Test extracting conditions using initial values (default behavior) """
1515 # Arrange
1616 species_data = [
17- Mock (species_id = "s1" , prepared = 10 .0 , initial = None ),
18- Mock (species_id = "s2" , prepared = 5 .0 , initial = None ),
17+ Mock (species_id = "s1" , prepared = 15 .0 , initial = 10.0 ),
18+ Mock (species_id = "s2" , prepared = 8 .0 , initial = 5.0 ),
1919 ]
2020 measurement = Mock (species_data = species_data , ph = 7.4 , temperature = 25.0 )
2121
22- # Act
22+ # Act - default uses "initial"
2323 conditions = _get_measurement_conditions (measurement )
2424
25- # Assert
25+ # Assert - should use initial values
2626 expected = {"s1" : 10.0 , "s2" : 5.0 , "ph" : 7.4 , "temperature" : 25.0 }
2727 assert conditions == expected
2828
@@ -42,22 +42,21 @@ def test_with_initial_values(self):
4242 expected = {"s1" : 8.0 , "s2" : 3.0 , "ph" : 6.8 , "temperature" : 30.0 }
4343 assert conditions == expected
4444
45- def test_prepared_takes_precedence_over_initial (self ):
46- """Test that prepared values take precedence over initial values """
45+ def test_attribute_selection_prepared (self ):
46+ """Test using prepared attribute over initial"""
4747 # Arrange
4848 species_data = [
4949 Mock (species_id = "s1" , prepared = 15.0 , initial = 10.0 ),
5050 Mock (species_id = "s2" , prepared = None , initial = 5.0 ),
5151 ]
5252 measurement = Mock (species_data = species_data , ph = None , temperature = None )
5353
54- # Act
55- conditions = _get_measurement_conditions (measurement )
54+ # Act - explicitly use "prepared" attribute
55+ conditions = _get_measurement_conditions (measurement , attribute = "prepared" )
5656
57- # Assert
57+ # Assert - only s1 included since s2 has no prepared value
5858 expected = {
5959 "s1" : 15.0 , # prepared value used
60- "s2" : 5.0 , # initial value used since prepared is None
6160 }
6261 assert conditions == expected
6362
@@ -66,16 +65,16 @@ def test_with_no_concentration_values(self):
6665 # Arrange
6766 species_data = [
6867 Mock (species_id = "s1" , prepared = None , initial = None ),
69- Mock (species_id = "s2" , prepared = 12.0 , initial = None ),
68+ Mock (species_id = "s2" , prepared = 12.0 , initial = 5.0 ),
7069 ]
7170 measurement = Mock (species_data = species_data , ph = 7.0 , temperature = None )
7271
73- # Act
72+ # Act - using default "initial" attribute
7473 conditions = _get_measurement_conditions (measurement )
7574
76- # Assert
75+ # Assert - only s2 included since s1 has no initial value
7776 expected = {
78- "s2" : 12 .0 , # only s2 included since s1 has no values
77+ "s2" : 5 .0 , # initial value used
7978 "ph" : 7.0 ,
8079 }
8180 assert conditions == expected
@@ -84,7 +83,7 @@ def test_with_no_environmental_conditions(self):
8483 """Test with measurement having no pH or temperature"""
8584 # Arrange
8685 species_data = [
87- Mock (species_id = "enzyme" , prepared = 1.0 , initial = None ),
86+ Mock (species_id = "enzyme" , initial = 1.0 , prepared = None ),
8887 ]
8988 measurement = Mock (species_data = species_data , ph = None , temperature = None )
9089
@@ -207,7 +206,7 @@ def test_with_different_conditions(self):
207206 enzmldoc = Mock (measurements = [measurement1 , measurement2 ])
208207
209208 # Act
210- result = group_measurements (enzmldoc )
209+ result = group_measurements (enzmldoc , attribute = "prepared" )
211210
212211 # Assert
213212 assert result == enzmldoc
@@ -299,7 +298,7 @@ def test_with_multiple_identical_and_different_conditions(self):
299298 )
300299
301300 # Act
302- group_measurements (enzmldoc )
301+ group_measurements (enzmldoc , attribute = "prepared" )
303302
304303 # Assert
305304 # measurement1, measurement2, and measurement4 should have the same group_id
@@ -311,10 +310,10 @@ def test_with_multiple_identical_and_different_conditions(self):
311310 def test_group_id_format (self ):
312311 """Test that group IDs follow the expected format"""
313312 # Arrange
314- species_data1 = [Mock (species_id = "s1" , prepared = 10.0 , initial = None )]
315- species_data2 = [Mock (species_id = "s1" , prepared = 15.0 , initial = None )]
316- species_data3 = [Mock (species_id = "s1" , prepared = 20.0 , initial = None )]
317- species_data4 = [Mock (species_id = "s1" , prepared = 20.0 , initial = None )]
313+ species_data1 = [Mock (species_id = "s1" , initial = 10.0 , prepared = None )]
314+ species_data2 = [Mock (species_id = "s1" , initial = 15.0 , prepared = None )]
315+ species_data3 = [Mock (species_id = "s1" , initial = 20.0 , prepared = None )]
316+ species_data4 = [Mock (species_id = "s1" , initial = 20.0 , prepared = None )]
318317
319318 measurement1 = Mock (
320319 species_data = species_data1 , ph = 7.4 , temperature = 25.0 , group_id = None
@@ -362,3 +361,132 @@ def test_with_valid_measurement_fixture(self, measurement_valid):
362361 for measurement in measurement_valid .measurements :
363362 assert measurement .group_id is not None
364363 assert measurement .group_id .startswith ("group_" )
364+
365+
366+ class TestGroupMeasurementsWithTolerance :
367+ """Test suite for group_measurements function with tolerance"""
368+
369+ def test_tolerance_exact_match (self ):
370+ """Test that identical values are grouped even with tolerance"""
371+ # Arrange
372+ species_data1 = [Mock (species_id = "s1" , prepared = None , initial = 200.0 )]
373+ species_data2 = [Mock (species_id = "s1" , prepared = None , initial = 200.0 )]
374+
375+ measurement1 = Mock (
376+ species_data = species_data1 , ph = 7.0 , temperature = 25.0 , group_id = None
377+ )
378+ measurement2 = Mock (
379+ species_data = species_data2 , ph = 7.0 , temperature = 25.0 , group_id = None
380+ )
381+
382+ enzmldoc = Mock (measurements = [measurement1 , measurement2 ])
383+
384+ # Act
385+ group_measurements (enzmldoc , tolerance = 0.05 )
386+
387+ # Assert
388+ assert measurement1 .group_id == "group_0"
389+ assert measurement2 .group_id == "group_0"
390+
391+ def test_tolerance_within_range (self ):
392+ """Test that values within tolerance are grouped together"""
393+ # Arrange - 200 and 201 should be grouped with 5% tolerance
394+ species_data1 = [Mock (species_id = "s1" , prepared = None , initial = 200.0 )]
395+ species_data2 = [Mock (species_id = "s1" , prepared = None , initial = 201.0 )]
396+
397+ measurement1 = Mock (
398+ species_data = species_data1 , ph = 7.0 , temperature = 25.0 , group_id = None
399+ )
400+ measurement2 = Mock (
401+ species_data = species_data2 , ph = 7.0 , temperature = 25.0 , group_id = None
402+ )
403+
404+ enzmldoc = Mock (measurements = [measurement1 , measurement2 ])
405+
406+ # Act - 1% difference should be within 5% tolerance
407+ group_measurements (enzmldoc , tolerance = 0.05 )
408+
409+ # Assert
410+ assert measurement1 .group_id == measurement2 .group_id
411+ assert measurement1 .group_id == "group_0"
412+
413+ def test_tolerance_outside_range (self ):
414+ """Test that values outside tolerance are grouped separately"""
415+ # Arrange - 200 and 220 should NOT be grouped with 5% tolerance
416+ species_data1 = [Mock (species_id = "s1" , prepared = None , initial = 200.0 )]
417+ species_data2 = [Mock (species_id = "s1" , prepared = None , initial = 220.0 )]
418+
419+ measurement1 = Mock (
420+ species_data = species_data1 , ph = 7.0 , temperature = 25.0 , group_id = None
421+ )
422+ measurement2 = Mock (
423+ species_data = species_data2 , ph = 7.0 , temperature = 25.0 , group_id = None
424+ )
425+
426+ enzmldoc = Mock (measurements = [measurement1 , measurement2 ])
427+
428+ # Act - 10% difference should be outside 5% tolerance
429+ group_measurements (enzmldoc , tolerance = 0.05 )
430+
431+ # Assert
432+ assert measurement1 .group_id != measurement2 .group_id
433+ assert measurement1 .group_id == "group_0"
434+ assert measurement2 .group_id == "group_1"
435+
436+ def test_tolerance_with_prepared_attribute (self ):
437+ """Test tolerance functionality with prepared attribute"""
438+ # Arrange
439+ species_data1 = [Mock (species_id = "s1" , prepared = 100.0 , initial = 50.0 )]
440+ species_data2 = [Mock (species_id = "s1" , prepared = 102.0 , initial = 60.0 )]
441+
442+ measurement1 = Mock (
443+ species_data = species_data1 , ph = 7.0 , temperature = 25.0 , group_id = None
444+ )
445+ measurement2 = Mock (
446+ species_data = species_data2 , ph = 7.0 , temperature = 25.0 , group_id = None
447+ )
448+
449+ enzmldoc = Mock (measurements = [measurement1 , measurement2 ])
450+
451+ # Act - using prepared attribute with tolerance
452+ group_measurements (enzmldoc , attribute = "prepared" , tolerance = 0.05 )
453+
454+ # Assert - 2% difference in prepared values should be within 5% tolerance
455+ assert measurement1 .group_id == measurement2 .group_id
456+ assert measurement1 .group_id == "group_0"
457+
458+ def test_tolerance_zero_values (self ):
459+ """Test tolerance handling with zero values"""
460+ # Arrange
461+ species_data1 = [Mock (species_id = "s1" , prepared = None , initial = 0.0 )]
462+ species_data2 = [Mock (species_id = "s1" , prepared = None , initial = 0.01 )]
463+
464+ measurement1 = Mock (
465+ species_data = species_data1 , ph = 7.0 , temperature = 25.0 , group_id = None
466+ )
467+ measurement2 = Mock (
468+ species_data = species_data2 , ph = 7.0 , temperature = 25.0 , group_id = None
469+ )
470+
471+ enzmldoc = Mock (measurements = [measurement1 , measurement2 ])
472+
473+ # Act - 0.01 difference should be outside 0.005 tolerance for zero values
474+ group_measurements (enzmldoc , tolerance = 0.005 )
475+
476+ # Assert
477+ assert measurement1 .group_id != measurement2 .group_id
478+
479+ def test_attribute_selection_default_initial (self ):
480+ """Test that default attribute is 'initial'"""
481+ # Arrange
482+ species_data = [Mock (species_id = "s1" , prepared = 15.0 , initial = 10.0 )]
483+ measurement = Mock (
484+ species_data = species_data , ph = 7.0 , temperature = 25.0 , group_id = None
485+ )
486+ enzmldoc = Mock (measurements = [measurement ])
487+
488+ # Act - no attribute specified, should default to "initial"
489+ group_measurements (enzmldoc )
490+
491+ # Assert - verify the function was called and measurement got grouped
492+ assert measurement .group_id == "group_0"
0 commit comments