Cecil Westerhof <ce...@decebal.nl> writes: > I need (sometimes) to repeatedly execute a function. For this I wrote > the below class. What do you think about it?
I wrote some unit test for the class. Is this the correct way to do this? For example in test_correct_params_no_start I check four things. Some people say you should not check more as one. By the way it was good that I defined __enter__ and __exit__. :-D #!/usr/bin/env python3 import unittest from threading import Timer from repeated_timer import repeated_timer class test_repeated_timer(unittest.TestCase): def test_interval_zero(self): with self.assertRaises(ValueError): rt = repeated_timer(dummy_fn, 0) def test_interval_negative(self): with self.assertRaises(ValueError): rt = repeated_timer(dummy_fn, -1) def test_interval_string(self): with self.assertRaises(TypeError): rt = repeated_timer(dummy_fn, '.4') def test_non_function(self): with self.assertRaises(TypeError): rt = repeated_timer('dummy_fn', .5) def test_correct_params_no_start(self): rt = repeated_timer(dummy_fn, .5) self.assertEqual(rt._fn, dummy_fn) self.assertEqual(rt._interval, .5) self.assertEqual(rt._timer, None) self.assertFalse(rt._is_running) def test_correct_params_do_start(self): with repeated_timer(dummy_fn, .375, True) as rt: self.assertEqual(rt._fn, dummy_fn) self.assertEqual(rt._interval, .375) self.assertTrue (isinstance(rt._timer, Timer), 'There should be a timer') self.assertTrue (rt._is_running, 'Should be running') def test__start_later(self): with repeated_timer(dummy_fn, .5) as rt: self.assertEqual(rt._fn, dummy_fn) self.assertEqual(rt._interval, .5) self.assertEqual(rt._timer, None) self.assertFalse(rt._is_running) rt.start() self.assertEqual(rt._fn, dummy_fn) self.assertEqual(rt._interval, .5) self.assertTrue (isinstance(rt._timer, Timer), 'There should be a timer') self.assertTrue (rt._is_running, 'Should be running') def dummy_fn(): pass if __name__ == '__main__': unittest.main() > from threading import Timer > > > > class repeated_timer(object): > def __init__(self, fn, interval, start = False): > if not callable(fn): > raise TypeError('{} is not a function'.format(fn)) > self._fn = fn > self._check_interval(interval) > self._interval = interval > self._timer = None > self._is_running = False > if start: > self.start() > > def _check_interval(self, interval): > if not type(interval) in [int, float]: > raise TypeError('{} is not numeric'.format(interval)) > if interval <= 0: > raise ValueError('{} is not greater as 0'.format(interval)) > > def _next(self): > self._timer = Timer(self._interval, self._run) > self._timer.start() > > def _run(self): > self._next() > self._fn() > > def set_interval(self, interval): > self._check_interval(interval) > self._interval = interval > > def start(self): > if not self._is_running: > self._next() > self._is_running = True > > def stop(self): > if self._is_running: > self._timer.cancel() > self._timer = None > self._is_running = False -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list