Skip to content

Commit

Permalink
test: refactor dispatcher tests. Move main tests to pytest model.
Browse files Browse the repository at this point in the history
  • Loading branch information
codito committed Mar 9, 2018
1 parent e30f574 commit 5a299cd
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 144 deletions.
2 changes: 1 addition & 1 deletion pomito/plugins/ui/qt/timer_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ def on_session_stop(self, *args, **kwargs):
self._notify_session_stop(reason)

def on_interrupt_start(self, *args, **kwargs):
return
pass

def on_interrupt_stop(self, *args, **kwargs):
self._interrupt_duration += kwargs['duration']
Expand Down
77 changes: 77 additions & 0 deletions tests/test_dispatcher.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# -*- coding: utf-8 -*-
"""Tests for message dispatcher."""

import unittest
from unittest.mock import Mock

import blinker

from pomito import main


class MessageTests(unittest.TestCase):
def test_send_calls_signal_send_with_kwargs(self):
mock_signal = Mock(blinker.Signal)
msg = main.Message(mock_signal, arg1="arg1", arg2=1)

msg.send()

mock_signal.send.assert_called_once_with(arg1="arg1", arg2=1)


class MessageDispatcherTests(unittest.TestCase):
def setUp(self):
dummy_signal = blinker.signal('dummy_signal')
self.test_message = main.Message(dummy_signal, arg1="arg1", arg2=1)
self.dispatcher = main.MessageDispatcher()
self.mock_callback = Mock()

def tearDown(self):
if self.dispatcher.is_alive():
self.dispatcher.stop()
self.dispatcher.join()

def test_queue_message_throws_for_invalid_message(self):
self.assertRaises(TypeError, self.dispatcher.queue_message, None)

def test_queue_message_doesnt_queue_message_if_there_are_no_receivers(self):
self.dispatcher.queue_message(self.test_message)

assert self.dispatcher._message_queue.qsize() == 0

def test_queue_message_queues_message_if_there_are_receivers(self):
self.test_message.signal.connect(Mock(), weak=False)

self.dispatcher.queue_message(self.test_message)

assert self.dispatcher._message_queue.qsize() == 1

def test_start_should_start_the_dispatcher_thread(self):
self.dispatcher.start()

assert self.dispatcher.is_alive()
assert self.dispatcher._stop_event.is_set() is False

def test_start_should_throw_if_dispatcher_is_already_started(self):
self.dispatcher.start()

self.assertRaises(RuntimeError, self.dispatcher.start)

def test_started_dispatcher_should_process_messages_in_queue(self):
self.test_message.signal.connect(self.mock_callback, weak=False)
self.dispatcher.start()

self.dispatcher.queue_message(self.test_message)

self.dispatcher._message_queue.join()
self.mock_callback.assert_called_once_with(None, arg1="arg1", arg2=1)

def test_stopped_dispatcher_shouldnt_process_messages_in_queue(self):
self.test_message.signal.connect(self.mock_callback, weak=False)
self.dispatcher.start()
self.dispatcher.stop()
self.dispatcher.join()

self.dispatcher.queue_message(self.test_message)

assert self.mock_callback.called is False
227 changes: 84 additions & 143 deletions tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@
"""Tests for the Main module."""

import os
import unittest
from unittest.mock import Mock, MagicMock, patch

import blinker
import tempfile
import pytest
from contextlib import contextmanager
from peewee import SqliteDatabase
from pyfakefs import fake_filesystem

from pomito import main
from pomito.plugins.ui import UIPlugin
Expand All @@ -19,188 +17,131 @@
from pomito.test import FakeTaskPlugin, FakeUIPlugin, PomitoTestFactory


class MessageTests(unittest.TestCase):
def test_send_calls_signal_send_with_kwargs(self):
mock_signal = Mock(blinker.Signal)
msg = main.Message(mock_signal, arg1="arg1", arg2=1)
"""
Tests for main class.
msg.send()
TODO
run: returns for invalid state
mock_signal.send.assert_called_once_with(arg1="arg1", arg2=1)
exit: sets the stop event
exit: calls close on all hooks
exit: writes the configuration
"""


class MessageDispatcherTests(unittest.TestCase):
def setUp(self):
dummy_signal = blinker.signal('dummy_signal')
self.test_message = main.Message(dummy_signal, arg1="arg1", arg2=1)
self.dispatcher = main.MessageDispatcher()
self.mock_callback = Mock()
@pytest.fixture(scope="function")
def memory_db():
return SqliteDatabase(':memory:')

def tearDown(self):
if self.dispatcher.is_alive():
self.dispatcher.stop()
self.dispatcher.join()

def test_queue_message_throws_for_invalid_message(self):
self.assertRaises(TypeError, self.dispatcher.queue_message, None)
@pytest.fixture(scope="function")
def pomito_instance(memory_db):
test_factory = PomitoTestFactory()

def test_queue_message_doesnt_queue_message_if_there_are_no_receivers(self):
self.dispatcher.queue_message(self.test_message)
dummy_config = test_factory.create_fake_config()
pomito = main.Pomito(config=dummy_config, database=memory_db)
_setup_pomito_plugins(pomito)
_setup_pomito_hooks(pomito)
return pomito

assert self.dispatcher._message_queue.qsize() == 0

def test_queue_message_queues_message_if_there_are_receivers(self):
self.test_message.signal.connect(Mock(), weak=False)
def test_default_hooks():
from pomito.hooks.activity import ActivityHook

self.dispatcher.queue_message(self.test_message)
pomito = main.Pomito()

assert self.dispatcher._message_queue.qsize() == 1
assert len(pomito._hooks) == 1
assert isinstance(pomito._hooks[0], ActivityHook)
pomito.exit()

def test_start_should_start_the_dispatcher_thread(self):
self.dispatcher.start()

assert self.dispatcher.is_alive()
assert self.dispatcher._stop_event.is_set() is False
def test_default_plugins():
from pomito.plugins import PLUGINS
default_plugins = ["console", "asana", "rtm", "text", "trello",
"nulltask", "qtapp"]

def test_start_should_throw_if_dispatcher_is_already_started(self):
self.dispatcher.start()
assert all([x in set(PLUGINS.keys()) for x in default_plugins])

self.assertRaises(RuntimeError, self.dispatcher.start)

def test_started_dispatcher_should_process_messages_in_queue(self):
self.test_message.signal.connect(self.mock_callback, weak=False)
self.dispatcher.start()
def test_custom_plugins():
pass

self.dispatcher.queue_message(self.test_message)

self.dispatcher._message_queue.join()
self.mock_callback.assert_called_once_with(None, arg1="arg1", arg2=1)
def test_initialize_creates_database_if_not_present():
with _setup_data_dir():
pomito = main.Pomito()
_setup_pomito_plugins(pomito)

def test_stopped_dispatcher_shouldnt_process_messages_in_queue(self):
self.test_message.signal.connect(self.mock_callback, weak=False)
self.dispatcher.start()
self.dispatcher.stop()
self.dispatcher.join()

self.dispatcher.queue_message(self.test_message)

assert self.mock_callback.called is False


class PomitoTests(unittest.TestCase):
"""
Tests for main class.
TODO
run: returns for invalid state
exit: sets the stop event
exit: calls close on all hooks
exit: writes the configuration
"""

def setUp(self):
test_factory = PomitoTestFactory()

# Encapsulate platform concerns
filesystem = fake_filesystem.FakeFilesystem()
os_module = fake_filesystem.FakeOsModule(filesystem)
test_factory.create_patch(self, 'os.path', os_module.path)
test_factory.create_patch(self, 'os.makedirs', os_module.makedirs)

self.dummy_db = SqliteDatabase(':memory:')
dummy_config = test_factory.create_fake_config()
self.main = main
self.pomito = main.Pomito(config=dummy_config, database=self.dummy_db)
self._setup_pomito_plugins(self.pomito)
self._setup_pomito_hooks(self.pomito)

def test_default_hooks(self):
from pomito.hooks.activity import ActivityHook

pomito = self.main.Pomito()
with patch('sqlite3.connect', MagicMock()):
pomito.initialize()

assert len(pomito._hooks) == 1
assert isinstance(pomito._hooks[0], ActivityHook)
assert pomito.get_db() is not None
pomito.exit()

def test_default_plugins(self):
from pomito.plugins import PLUGINS
default_plugins = ["console", "asana", "rtm", "text", "trello",
"nulltask", "qtapp"]

assert all([x in set(PLUGINS.keys()) for x in default_plugins])
def test_initialize_uses_injected_database():
dummy_db = SqliteDatabase(':memory:')
pomito = main.Pomito(database=dummy_db)
_setup_pomito_plugins(pomito)

def test_custom_plugins(self):
pass
with patch('sqlite3.connect', MagicMock()):
pomito.initialize()

def test_initialize_creates_database_if_not_present(self):
with self._setup_data_dir():
pomito = self.main.Pomito()
self._setup_pomito_plugins(pomito)
assert pomito.get_db() == dummy_db
pomito.exit()

with patch('sqlite3.connect', MagicMock()):
pomito.initialize()

assert pomito.get_db() is not None
pomito.exit()

def test_initialize_uses_injected_database(self):
dummy_db = SqliteDatabase(':memory:')
pomito = self.main.Pomito(database=dummy_db)
self._setup_pomito_plugins(pomito)
def test_initialize_setup_plugins_and_hooks():
with _setup_data_dir():
pomito = main.Pomito()
_setup_pomito_plugins(pomito)
_setup_pomito_hooks(pomito)

with patch('sqlite3.connect', MagicMock()):
pomito.initialize()

assert pomito.get_db() == dummy_db
assert pomito.ui_plugin.initialize.call_count == 1
assert pomito.task_plugin.initialize.call_count == 1
assert pomito._hooks[0].initialize.call_count == 1
pomito.exit()

def test_initialize_setup_plugins_and_hooks(self):
with self._setup_data_dir():
pomito = self.main.Pomito()
self._setup_pomito_plugins(pomito)
self._setup_pomito_hooks(pomito)

with patch('sqlite3.connect', MagicMock()):
pomito.initialize()
def test_run_no_op_for_invalid_state(pomito_instance):
pomito_instance.run()

pomito_instance.ui_plugin.run.assert_not_called()


def test_run_invokes_ui_plugin(pomito_instance):
pomito_instance.ui_plugin = FakeUIPlugin()
pomito_instance.task_plugin = FakeTaskPlugin()

assert pomito.ui_plugin.initialize.call_count == 1
assert pomito.task_plugin.initialize.call_count == 1
assert pomito._hooks[0].initialize.call_count == 1
pomito.exit()
pomito_instance.run()

def test_run_no_op_for_invalid_state(self):
self.pomito.run()
assert pomito_instance.ui_plugin.started

self.pomito.ui_plugin.run.assert_not_called()

def test_run_invokes_ui_plugin(self):
self.pomito.ui_plugin = FakeUIPlugin()
self.pomito.task_plugin = FakeTaskPlugin()
def test_exit_closes_database(pomito_instance, memory_db):
pomito_instance.exit()

self.pomito.run()
assert memory_db.is_closed

assert self.pomito.ui_plugin.started

def test_exit_closes_database(self):
self.pomito.exit()
def _setup_pomito_plugins(pomito):
pomito.ui_plugin = Mock(spec=UIPlugin)
pomito.task_plugin = Mock(spec=TaskPlugin)

assert self.dummy_db.is_closed

def _setup_pomito_plugins(self, pomito):
pomito.ui_plugin = Mock(spec=UIPlugin)
pomito.task_plugin = Mock(spec=TaskPlugin)
def _setup_pomito_hooks(pomito):
pomito._hooks[0] = Mock(spec=Hook)

def _setup_pomito_hooks(self, pomito):
pomito._hooks[0] = Mock(spec=Hook)

@contextmanager
def _setup_data_dir(self):
with tempfile.TemporaryDirectory() as tmpdir:
data_dir = self.main.DATA_DIR
self.main.DATA_DIR = os.path.join(tmpdir, "pomito")
try:
yield
finally:
self.main.DATA_DIR = data_dir
@contextmanager
def _setup_data_dir():
with tempfile.TemporaryDirectory() as tmpdir:
data_dir = main.DATA_DIR
main.DATA_DIR = os.path.join(tmpdir, "pomito")
try:
yield
finally:
main.DATA_DIR = data_dir

0 comments on commit 5a299cd

Please sign in to comment.