diff --git a/test/test_adjusters.py b/test/test_adjusters.py index 1e2220f..e718137 100644 --- a/test/test_adjusters.py +++ b/test/test_adjusters.py @@ -3,6 +3,8 @@ import unittest import unittest.mock as mock import pipeline.adjusters as adjusters +from test.mocks import MockFeature, MockInterval + class TestAdjuster(unittest.TestCase): """Test the generic Adjuster class""" @@ -36,7 +38,7 @@ class TestTargetTimeAdjuster(unittest.TestCase): tta = adjusters.TargetTimeAdjuster() features = [] for i in range(1, 5): - features.append(mock.Mock(duration=i*1.0)) + features.append(make_feature(duration=i*1.0)) self.assertEqual(tta._features_total_time(features), 10.0) self.assertEqual(tta._features_total_time([]), 0.0) @@ -175,3 +177,106 @@ class TestTargetTimeAdjuster(unittest.TestCase): make_feature(duration=1.0, score=1.0) ] self.assertEqual(tta._sort_by_score_time(features), [features[2], features[3], features[0], features[1]]) + + + def test_adjust_changes(self): + """Test adjusting of list of Features using TTA -- changes to list of Features + + All cases have total time > target time. + + In the cases, specification is Feature(duration, score) + Cases: + - target = 30.0, margin = 0.0 + + [(15.0, 1.0), (10.0, 1.0), (12.0, 1.0)] --> [(15.0, 1.0), (12.0, 1.0)] # scores equal, drop smallest + + [(15.0, 2.0), (10.0, 2.0), (12.0, 1.0)] --> [(15.0, 1.0), (10.0, 1.0)] # drop lowest scoring (1) + + [(15.0, 1.0), (10.0, 1.0), (12.0, 2.0)] --> [(15.0, 1.0), (12.0, 2.0)] # drop lowest scoring (2) + + - target = 30.0, margin = 4.0 + + [(15.0, 1.0), (10.0, 2.0), (12.0, 1.0)] --> [(15.0, 1.0), (12.0, 1.0)] # not lowest scoring, but within margin + + [(16.0, 1.0), (16.0, 1.0), (1.0, 1.0), (1.0, 1.0)] --> [(16.0, 1.0), (16.0, 1.0)] # drop multiple lowest scoring, shortest duration + + """ + # target 30.0, margin 0.0 cases + target, margin = 30.0, 0.0 + + with self.subTest(f"target {target} margin {margin}"): + with self.subTest("scores equal"): + features = [ + make_feature(duration=15.0, score=1.0), + make_feature(duration=10.0, score=1.0), + make_feature(duration=12.0, score=1.0) + ] + tta = adjusters.TargetTimeAdjuster(features=features, target_time=target, margin=margin) + expected = [features[0], features[2]] + output = tta.adjust() + self.assertEqual(len(output), 2) + self.assertEqual(output, expected) + self.assertEqual(tta.features, expected) + + with self.subTest("drop lowest scoring (1)"): + features = [ + make_feature(duration=15.0, score=2.0), + make_feature(duration=10.0, score=2.0), + make_feature(duration=12.0, score=1.0) + ] + tta = adjusters.TargetTimeAdjuster(features=features, target_time=target, margin=margin) + expected = [features[0], features[1]] + output = tta.adjust() + self.assertEqual(len(output), 2) + self.assertEqual(output, expected) + self.assertEqual(tta.features, expected) + + with self.subTest("drop lowest scoring (2)"): + features = [ + make_feature(duration=15.0, score=1.0), + make_feature(duration=10.0, score=1.0), + make_feature(duration=12.0, score=2.0) + ] + tta = adjusters.TargetTimeAdjuster(features=features, target_time=target, margin=margin) + expected = [features[0], features[2]] + output = tta.adjust() + self.assertEqual(len(output), 2) + self.assertEqual(output, expected) + self.assertEqual(tta.features, expected) + + # target 30.0, margin 4.0 cases + target, margin, strategy = 30.0, 4.0, adjusters.TargetTimeAdjuster._STRATEGY.ABSOLUTE + + with self.subTest(f"target {target} margin {margin}"): + with self.subTest("not lowest scoring, but within margin"): + # explanation: dropping the 10.0 feature would put us at 27.0, which is within the margin (26.0, 34.0) + features = [ + make_feature(duration=15.0, score=1.0), + make_feature(duration=10.0, score=2.0), + make_feature(duration=12.0, score=1.0) + ] + tta = adjusters.TargetTimeAdjuster(features=features, target_time=target, + margin=margin, strategy=strategy) + expected = [features[0], features[2]] + output = tta.adjust() + self.assertEqual(len(output), 2) + self.assertEqual(output, expected) + self.assertEqual(tta.features, expected) + + with self.subTest("drop multiple lowest scoring, shortest duration"): + # explanation: dropping the 1.0 features would put us at 32.0, which is within the margin (26.0, 34.0) + features = [ + make_feature(duration=16.0, score=1.0), + make_feature(duration=16.0, score=1.0), + make_feature(duration=1.0, score=1.0), + make_feature(duration=1.0, score=1.0), + make_feature(duration=1.0, score=1.0), + make_feature(duration=1.0, score=1.0) + ] + tta = adjusters.TargetTimeAdjuster(features=features, target_time=target, + margin=margin, strategy=strategy) + expected = [features[0], features[1], features[2], features[3]] + output = tta.adjust() + self.assertEqual(len(output), 4) + self.assertEqual(output, expected) + self.assertEqual(tta.features, expected) + + +def make_feature(duration, score=1.0): + """Helper function to create a MockFeature from duration and score""" + return MockFeature(interval=MockInterval.from_duration(duration), score=score)