From fcfc1773bcaaf030cbdf7445102f7fc2bd4d885e Mon Sep 17 00:00:00 2001 From: Rob Hallam <0504004h@student.gla.ac.uk> Date: Fri, 19 Jul 2024 14:24:07 +0100 Subject: [PATCH] feat: add suite of tests for utils module This covers: - Source - SourceMedia - Interval --- test/test_utils.py | 173 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 test/test_utils.py diff --git a/test/test_utils.py b/test/test_utils.py new file mode 100644 index 0000000..a98997e --- /dev/null +++ b/test/test_utils.py @@ -0,0 +1,173 @@ +"""Test cases for utils""" +import unittest + +import pipeline.utils as utils + + +class TestSource(unittest.TestCase): + """Source is a container for source, path, and provider of a media file + + source -- the source of the media file (eg, a URL or a local path) + path -- the path to the media file + provider -- the provider of the media file (eg, "FileInputJSON") + + Accessing the object should return the path to the media file. + + Methods: + + duration() -- return the duration of the media file (uses ffprobe, result is cached) + """ + # Happy path tests + def setUp(self): + self.source = "audio_clips/testclip-5min.aac" + self.path = "audio_clips/testclip-5min.aac" + self.provider = "FileInputJSON" + self._duration = 306.121214 # duration of testclip-5min.aac + + def test_init(self): + source = utils.Source(self.source, self.path, self.provider) + self.assertEqual(source.source, self.source) + self.assertEqual(source.path, self.path) + self.assertEqual(source.provider, self.provider) + + def test_str(self): + """Accessing the object should return the path to the media file""" + source = utils.Source(self.source, self.path, self.provider) + self.assertEqual(str(source), self.path) + + def test_repr(self): + source = utils.Source(self.source, self.path, self.provider) + self.assertEqual(repr(source), f"Source({self.source}, {self.path}, {self.provider})") + + def test_duration(self): + """Use a mock duration of 306.121214 for the test clip""" + source = utils.Source(self.source, self.path, self.provider) + self.assertEqual(source.duration(), self._duration) + + # Sad path tests + def test_init_no_source(self): + with self.assertRaises(ValueError): + utils.Source("", self.path, self.provider) + + def test_init_no_path(self): + with self.assertRaises(ValueError): + utils.Source(self.source, "", self.provider) + + def test_init_no_provider(self): + with self.assertRaises(ValueError): + utils.Source(self.source, self.path, "") + + def test_duration_no_file(self): + """Test that duration raises FileNotFoundError if the file does not exist""" + source = utils.Source(self.source, "fakepath-noexist!😇", self.provider) + # if that file actually exists I'll eat my hat + with self.assertRaises(FileNotFoundError): + source.duration() + + +class TestSourceMedia(unittest.TestCase): + """SourceMedia is a container for Source objects""" + class FakeSource(): + """Fake source object for testing SourceMedia + + Since SourceMedia doesn't actually access any of the attributes of Source objects, + we can use a very empty class for testing. + """ + + def setUp(self): + self.source1 = self.FakeSource() + self.source2 = self.FakeSource() + self.source3 = self.FakeSource() + self.sources = [self.source1, self.source2, self.source3] + + def test_init(self): + source_media = utils.SourceMedia(sources=self.sources) + self.assertEqual(source_media.sources, self.sources) + + def test_iter(self): + source_media = utils.SourceMedia(sources=self.sources) + self.assertEqual(list(source_media), self.sources) + + +class TestInterval(unittest.TestCase): + """Interval is a container for start, end and duration attributes""" + def setUp(self): + self.start = 0 + self.end = 10 + self.duration = 10 + + # Happy path tests + + def test_init_start_end(self): + """Create an Interval using start and end attributes""" + interval = utils.Interval(start=self.start, end=self.end) + self.assertEqual(interval.start, self.start) + self.assertEqual(interval.end, self.end) + self.assertEqual(interval.duration, self.duration) + + def test_init_start_duration(self): + """Create an Interval using start and duration attributes""" + interval = utils.Interval(start=self.start, duration=self.duration) + self.assertEqual(interval.start, self.start) + self.assertEqual(interval.end, self.end) + self.assertEqual(interval.duration, self.duration) + + def test_init_end_duration(self): + """Create an Interval using end and duration attributes""" + interval = utils.Interval(end=self.end, duration=self.duration) + self.assertEqual(interval.start, self.start) + self.assertEqual(interval.end, self.end) + self.assertEqual(interval.duration, self.duration) + + def test_from_start_classmethod(self): + """Create an Interval using the from_start classmethod (ie start attribute only- uses default duration)""" + interval = utils.Interval.from_start(start=self.start) + self.assertEqual(interval.start, self.start) + self.assertEqual(interval.end, interval.start + utils.Interval.DEFAULT_DURATION) + self.assertEqual(interval.duration, utils.Interval.DEFAULT_DURATION) + + def test_from_end_classmethod(self): + """Create an Interval using the from_end classmethod (ie end attribute only- uses default duration)""" + interval = utils.Interval.from_end(end=self.end) + self.assertEqual(interval.start, interval.end - utils.Interval.DEFAULT_DURATION) + self.assertEqual(interval.end, self.end) + self.assertEqual(interval.duration, utils.Interval.DEFAULT_DURATION) + + def test_repr(self): + interval = utils.Interval(start=self.start, end=self.end) + self.assertEqual(repr(interval), f"Interval({self.start}, {self.end}, {self.duration})") + + def test_lt(self): + """Test the __lt__ method used for sorting Interval objects based on start time + + If the start times are equal, the interval with the smaller end time is considered smaller + """ + interval1 = utils.Interval(start=0, end=10) + interval2 = utils.Interval(start=0, end=15) + interval3 = utils.Interval(start=5, end=10) + interval4 = utils.Interval(start=5, end=15) + self.assertTrue(interval1 < interval2) # same start, interval1 has smaller end + self.assertTrue(interval1 < interval3) # interval1 start is smaller + self.assertTrue(interval3 > interval2) # interval3 start is larger + self.assertTrue(interval3 < interval4) # same start, interval3 has smaller end + + def test_move_start(self): + """Test the move_start method - changes start time to time specified, keeps end time constant""" + interval = utils.Interval(start=self.start, end=self.end) + interval.move_start(5) + self.assertEqual(interval.start, 5) + self.assertEqual(interval.end, 10) + self.assertEqual(interval.duration, 5) + + def test_move_start_relative(self): + """Test the move_start method with relative=True - changes start time by a relative amount""" + interval = utils.Interval(start=self.start, end=self.end) + interval.move_start(2, relative=True) + self.assertEqual(interval.start, 2) + self.assertEqual(interval.end, 10) + self.assertEqual(interval.duration, 8) + + + +if __name__ == "__main__": + unittest.main()