Add test cases for EventScheduler class

====  Tech Notes ====
- Add test cases
- Slight refactoring of EventScheduler class to make it easier to test
pull/1189/head
Åke Forslund 2017-09-25 14:15:12 +02:00
parent 28e0ae9200
commit 3004aada98
2 changed files with 98 additions and 24 deletions

View File

@ -51,11 +51,12 @@ class EventScheduler(Thread):
Load json data with active events from json file. Load json data with active events from json file.
""" """
if isfile(self.schedule_file): if isfile(self.schedule_file):
json_data = {}
with open(self.schedule_file) as f: with open(self.schedule_file) as f:
try: try:
json_data = json.load(f) json_data = json.load(f)
except Exception as e: except Exception as e:
LOG.error(e) LOG.error(e.message)
current_time = time.time() current_time = time.time()
for key in json_data: for key in json_data:
event_list = json_data[key] event_list = json_data[key]
@ -97,31 +98,34 @@ class EventScheduler(Thread):
def run(self): def run(self):
while self.isRunning: while self.isRunning:
# Remove events self.check_state()
self.remove_events()
# Fetch newly scheduled events
self.fetch_new_events()
# Update events
self.update_events()
# Check all events
for event in self.events:
current_time = time.time()
e = self.events[event]
# Get scheduled times that has passed
passed = [(t, r, d) for (t, r, d) in e if t <= current_time]
# and remaining times that we're still waiting for
remaining = [(t, r, d) for t, r, d in e if t > current_time]
# Trigger registered methods
for sched_time, repeat, data in passed:
self.emitter.emit(Message(event, data))
# if this is a repeated event add a new trigger time
if repeat:
remaining.append((sched_time + repeat, repeat, data))
# update list of events
self.events[event] = remaining
time.sleep(0.5) time.sleep(0.5)
def check_state(self):
# Remove events
self.remove_events()
# Fetch newly scheduled events
self.fetch_new_events()
# Update events
self.update_events()
# Check all events
for event in self.events:
current_time = time.time()
e = self.events[event]
# Get scheduled times that has passed
passed = [(t, r, d) for (t, r, d) in e if t <= current_time]
# and remaining times that we're still waiting for
remaining = [(t, r, d) for t, r, d in e if t > current_time]
# Trigger registered methods
for sched_time, repeat, data in passed:
self.emitter.emit(Message(event, data))
# if this is a repeated event add a new trigger time
if repeat:
remaining.append((sched_time + repeat, repeat, data))
# update list of events
self.events[event] = remaining
def schedule_event(self, event, sched_time, repeat=None, data=None): def schedule_event(self, event, sched_time, repeat=None, data=None):
""" Send event to thread using thread safe queue. """ """ Send event to thread using thread safe queue. """
data = data or {} data = data or {}

View File

@ -0,0 +1,70 @@
import unittest
import mock
import time
from mycroft.skills.event_scheduler import EventScheduler
"""
Test cases regarding the event scheduler.
"""
class TestEventScheduler(unittest.TestCase):
@mock.patch('threading.Thread')
@mock.patch('json.dump')
@mock.patch('mycroft.skills.event_scheduler.open')
def test_create(self, mock_open, mock_json_dump, mock_thread):
"""
Test creating and shutting down event_scheduler.
"""
mock_open.return_value = mock.MagicMock(spec=file)
emitter = mock.MagicMock()
es = EventScheduler(emitter)
es.shutdown()
self.assertEquals(mock_json_dump.call_args[0][0], {})
@mock.patch('threading.Thread')
@mock.patch('json.dump')
@mock.patch('mycroft.skills.event_scheduler.open')
def test_add_remove(self, mock_open, mock_json_dump, mock_thread):
"""
Test add an event and then remove it.
"""
# Thread start is mocked so will not actually run the thread loop
mock_open.return_value = mock.MagicMock(spec=file)
emitter = mock.MagicMock()
es = EventScheduler(emitter)
es.schedule_event('test', 90000000000, None)
es.schedule_event('test-2', 90000000000, None)
es.check_state() # run one cycle
self.assertTrue('test' in es.events)
self.assertTrue('test-2' in es.events)
es.remove_event('test')
es.check_state() # run one cycle
self.assertTrue('test' not in es.events)
self.assertTrue('test-2' in es.events)
es.shutdown()
@mock.patch('threading.Thread')
@mock.patch('json.load')
@mock.patch('json.dump')
@mock.patch('mycroft.skills.event_scheduler.open')
def test_save(self, mock_open, mock_dump, mock_load, mock_thread):
"""
Test save functionality.
"""
mock_open.return_value = mock.MagicMock(spec=file)
emitter = mock.MagicMock()
es = EventScheduler(emitter)
es.schedule_event('test', 900000000000, None)
es.schedule_event('test-repeat', 910000000000, 60)
es.check_state()
es.shutdown()
self.assertEquals(mock_dump.call_args[0][0],
{'test': [(900000000000, None, {})]})