diff --git a/pyloopkit/carb_math.py b/pyloopkit/carb_math.py index ba96c60..5746358 100644 --- a/pyloopkit/carb_math.py +++ b/pyloopkit/carb_math.py @@ -444,6 +444,9 @@ def parabolic_percent_absorption_at_time(time, absorption_time): Output: Percent of absorbed carbs """ + if absorption_time <= 0: + raise ValueError("absorption_time must be positive") + if time < 0: return 0 @@ -866,6 +869,8 @@ def carb_glucose_effect( Output: Glucose effect (mg/dL/min) """ + if carb_ratio <= 0: + raise ValueError("carb_ratio must be positive") return insulin_sensitivity / carb_ratio * absorbed_carbs( carb_start, diff --git a/tests/test_carb_math.py b/tests/test_carb_math.py index f37a4ef..36bccea 100644 --- a/tests/test_carb_math.py +++ b/tests/test_carb_math.py @@ -15,7 +15,9 @@ #from . import path_grabber # pylint: disable=unused-import from .loop_kit_tests import load_fixture from pyloopkit.carb_math import (map_, carb_glucose_effects, carbs_on_board, - dynamic_carbs_on_board, dynamic_glucose_effects) + dynamic_carbs_on_board, dynamic_glucose_effects, + parabolic_percent_absorption_at_time, + parabolic_absorbed_carbs, carb_glucose_effect) class TestCarbKitFunctions(unittest.TestCase): @@ -845,6 +847,35 @@ def test_dynamic_glucose_effect_absorption_never_fully_observed(self): expected_values[i], effect_values[i], 2 ) + def test_parabolic_percent_absorption_rejects_nonpositive_absorption(self): + # absorption_time is divided into, so a non-positive value previously + # raised an opaque ZeroDivisionError rather than validating the input + self.assertRaises( + ValueError, parabolic_percent_absorption_at_time, 0, 0 + ) + self.assertRaises( + ValueError, parabolic_percent_absorption_at_time, 5, -10 + ) + # a positive absorption time is unaffected + self.assertEqual(parabolic_percent_absorption_at_time(0, 120), 0) + self.assertEqual(parabolic_percent_absorption_at_time(240, 120), 1) + self.assertRaises( + ValueError, parabolic_absorbed_carbs, 10, 0, 0 + ) + + def test_carb_glucose_effect_rejects_nonpositive_carb_ratio(self): + # carb_ratio is divided into, so zero previously raised an opaque + # ZeroDivisionError rather than validating the input + a_date = datetime(2019, 1, 1, 12, 0, 0) + self.assertRaises( + ValueError, carb_glucose_effect, + a_date, 10, a_date, 0, 40, 120, 10 + ) + self.assertRaises( + ValueError, carb_glucose_effect, + a_date, 10, a_date, -5, 40, 120, 10 + ) + if __name__ == '__main__': unittest.main()