From 230c06c83ccc23b7fa06e8bebb20343e9f583d71 Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Mon, 11 Feb 2013 11:34:24 +0200 Subject: [PATCH 1/5] Change the importing of plugins to use the "imp" module in an effort to get around the UNO import errors. --- openlp/core/lib/pluginmanager.py | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/openlp/core/lib/pluginmanager.py b/openlp/core/lib/pluginmanager.py index a6fd2a848..be171be21 100644 --- a/openlp/core/lib/pluginmanager.py +++ b/openlp/core/lib/pluginmanager.py @@ -32,6 +32,7 @@ Provide plugin management import os import sys import logging +import imp from openlp.core.lib import Plugin, PluginStatus, Registry @@ -55,11 +56,8 @@ class PluginManager(object): """ log.info(u'Plugin manager Initialising') Registry().register(u'plugin_manager', self) - if not plugin_dir in sys.path: - log.debug(u'Inserting %s into sys.path', plugin_dir) - sys.path.insert(0, plugin_dir) - self.basepath = os.path.abspath(plugin_dir) - log.debug(u'Base path %s ', self.basepath) + self.base_path = os.path.abspath(plugin_dir) + log.debug(u'Base path %s ', self.base_path) self.plugins = [] log.info(u'Plugin manager Initialised') @@ -73,9 +71,8 @@ class PluginManager(object): """ log.info(u'Finding plugins') - startdepth = len(os.path.abspath(plugin_dir).split(os.sep)) - log.debug(u'finding plugins in %s at depth %d', - unicode(plugin_dir), startdepth) + start_depth = len(os.path.abspath(plugin_dir).split(os.sep)) + log.debug(u'finding plugins in %s at depth %d', unicode(plugin_dir), start_depth) for root, dirs, files in os.walk(plugin_dir): # TODO Presentation plugin is not yet working on Mac OS X. # For now just ignore it. The following code will hide it @@ -88,22 +85,20 @@ class PluginManager(object): for name in files: if name.endswith(u'.py') and not name.startswith(u'__'): path = os.path.abspath(os.path.join(root, name)) - thisdepth = len(path.split(os.sep)) - if thisdepth - startdepth > 2: + this_depth = len(path.split(os.sep)) + if this_depth - start_depth > 2: # skip anything lower down break - modulename = os.path.splitext(path)[0] - prefix = os.path.commonprefix([self.basepath, path]) - # hack off the plugin base path - modulename = modulename[len(prefix) + 1:] - modulename = modulename.replace(os.path.sep, '.') + module_name = name[:-3] # import the modules - log.debug(u'Importing %s from %s. Depth %d', modulename, path, thisdepth) + log.debug(u'Importing %s from %s. Depth %d', module_name, root, this_depth) try: - __import__(modulename, globals(), locals(), []) + fp, path_name, description = imp.find_module(module_name, [root]) + imp.load_module(module_name, fp, path_name, description) + #__import__(module_name, globals(), locals(), []) except ImportError, e: log.exception(u'Failed to import module %s on path %s for reason %s', - modulename, path, e.args[0]) + module_name, path, e.args[0]) plugin_classes = Plugin.__subclasses__() plugin_objects = [] for p in plugin_classes: From a2125e09543fd08a656693096d9f04f037e10510 Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Mon, 11 Feb 2013 11:43:26 +0200 Subject: [PATCH 2/5] Add some comments to make things clearer. --- openlp/core/lib/pluginmanager.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openlp/core/lib/pluginmanager.py b/openlp/core/lib/pluginmanager.py index be171be21..6dba74998 100644 --- a/openlp/core/lib/pluginmanager.py +++ b/openlp/core/lib/pluginmanager.py @@ -93,9 +93,12 @@ class PluginManager(object): # import the modules log.debug(u'Importing %s from %s. Depth %d', module_name, root, this_depth) try: + # Use the "imp" library to try to get around a problem with the PyUNO library which + # monkey-patches the __import__ function to do some magic. This causes issues with our tests. + # First, try to find the module we want to import, searching the directory in ``root`` fp, path_name, description = imp.find_module(module_name, [root]) + # Then load the module (do the actual import) using the details from ``find_module()`` imp.load_module(module_name, fp, path_name, description) - #__import__(module_name, globals(), locals(), []) except ImportError, e: log.exception(u'Failed to import module %s on path %s for reason %s', module_name, path, e.args[0]) From f822aed40fd84446216c323365489da86607002e Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Mon, 11 Feb 2013 15:22:13 +0200 Subject: [PATCH 3/5] Add some tests around the PluginManager class. --- openlp/core/lib/pluginmanager.py | 3 +- .../openlp_core_lib/test_pluginmanager.py | 373 ++++++++++++++++++ .../openlp_core_lib/test_registry.py | 8 +- 3 files changed, 380 insertions(+), 4 deletions(-) create mode 100644 tests/functional/openlp_core_lib/test_pluginmanager.py diff --git a/openlp/core/lib/pluginmanager.py b/openlp/core/lib/pluginmanager.py index 6dba74998..cdd99a9e0 100644 --- a/openlp/core/lib/pluginmanager.py +++ b/openlp/core/lib/pluginmanager.py @@ -140,7 +140,8 @@ class PluginManager(object): for plugin in self.plugins: if plugin.status is not PluginStatus.Disabled: plugin.createSettingsTab(settings_form) - settings_form.plugins = self.plugins + if settings_form: + settings_form.plugins = self.plugins def hook_import_menu(self, import_menu): """ diff --git a/tests/functional/openlp_core_lib/test_pluginmanager.py b/tests/functional/openlp_core_lib/test_pluginmanager.py new file mode 100644 index 000000000..3539373e0 --- /dev/null +++ b/tests/functional/openlp_core_lib/test_pluginmanager.py @@ -0,0 +1,373 @@ +""" +Package to test the openlp.core.lib.pluginmanager package. +""" +from unittest import TestCase + +from mock import MagicMock + +from openlp.core.lib.pluginmanager import PluginManager +from openlp.core.lib import Registry, PluginStatus + + +class TestPluginManager(TestCase): + """ + Test the PluginManager class + """ + + def setUp(self): + """ + Some pre-test setup required. + """ + Registry.create() + Registry().register(u'service_list', MagicMock()) + + def hook_media_manager_with_disabled_plugin_test(self): + """ + Test running the hook_media_manager() method with a disabled plugin + """ + # GIVEN: A PluginManager instance and a list with a mocked up plugin whose status is set to Disabled + mocked_plugin = MagicMock() + mocked_plugin.status = PluginStatus.Disabled + plugin_manager = PluginManager('') + plugin_manager.plugins = [mocked_plugin] + + # WHEN: We run hook_media_manager() + plugin_manager.hook_media_manager() + + # THEN: The createMediaManagerItem() method should have been called + assert mocked_plugin.createMediaManagerItem.call_count == 0, \ + u'The createMediaManagerItem() method should not have been called.' + + def hook_media_manager_with_active_plugin_test(self): + """ + Test running the hook_media_manager() method with an active plugin + """ + # GIVEN: A PluginManager instance and a list with a mocked up plugin whose status is set to Active + mocked_plugin = MagicMock() + mocked_plugin.status = PluginStatus.Active + plugin_manager = PluginManager('') + plugin_manager.plugins = [mocked_plugin] + + # WHEN: We run hook_media_manager() + plugin_manager.hook_media_manager() + + # THEN: The createMediaManagerItem() method should have been called + mocked_plugin.createMediaManagerItem.assert_called_with() + + def hook_settings_tabs_with_disabled_plugin_and_no_form_test(self): + """ + Test running the hook_settings_tabs() method with a disabled plugin and no form + """ + # GIVEN: A PluginManager instance and a list with a mocked up plugin whose status is set to Disabled + mocked_plugin = MagicMock() + mocked_plugin.status = PluginStatus.Disabled + plugin_manager = PluginManager('') + plugin_manager.plugins = [mocked_plugin] + + # WHEN: We run hook_settings_tabs() + plugin_manager.hook_settings_tabs() + + # THEN: The createSettingsTab() method should have been called + assert mocked_plugin.createMediaManagerItem.call_count == 0, \ + u'The createMediaManagerItem() method should not have been called.' + + def hook_settings_tabs_with_disabled_plugin_and_mocked_form_test(self): + """ + Test running the hook_settings_tabs() method with a disabled plugin and a mocked form + """ + # GIVEN: A PluginManager instance and a list with a mocked up plugin whose status is set to Disabled + mocked_plugin = MagicMock() + mocked_plugin.status = PluginStatus.Disabled + mocked_settings_form = MagicMock() + plugin_manager = PluginManager('') + plugin_manager.plugins = [mocked_plugin] + + # WHEN: We run hook_settings_tabs() + plugin_manager.hook_settings_tabs(mocked_settings_form) + + # THEN: The createSettingsTab() method should not have been called, but the plugins lists should be the same + assert mocked_plugin.createSettingsTab.call_count == 0, \ + u'The createMediaManagerItem() method should not have been called.' + self.assertEqual(mocked_settings_form.plugins, plugin_manager.plugins, + u'The plugins on the settings form should be the same as the plugins in the plugin manager') + + def hook_settings_tabs_with_active_plugin_and_no_form_test(self): + """ + Test running the hook_settings_tabs() method with an active plugin and no settings form + """ + # GIVEN: A PluginManager instance and a list with a mocked up plugin whose status is set to Active + mocked_plugin = MagicMock() + mocked_plugin.status = PluginStatus.Active + plugin_manager = PluginManager('') + plugin_manager.plugins = [mocked_plugin] + + # WHEN: We run hook_settings_tabs() + plugin_manager.hook_settings_tabs() + + # THEN: The createSettingsTab() method should have been called + mocked_plugin.createSettingsTab.assert_called_with(None) + + def hook_settings_tabs_with_active_plugin_and_mocked_form_test(self): + """ + Test running the hook_settings_tabs() method with an active plugin and a mocked settings form + """ + # GIVEN: A PluginManager instance and a list with a mocked up plugin whose status is set to Active + mocked_plugin = MagicMock() + mocked_plugin.status = PluginStatus.Active + mocked_settings_form = MagicMock() + plugin_manager = PluginManager('') + plugin_manager.plugins = [mocked_plugin] + + # WHEN: We run hook_settings_tabs() + plugin_manager.hook_settings_tabs(mocked_settings_form) + + # THEN: The createMediaManagerItem() method should have been called with the mocked settings form + mocked_plugin.createSettingsTab.assert_called_with(mocked_settings_form) + self.assertEqual(mocked_settings_form.plugins, plugin_manager.plugins, + u'The plugins on the settings form should be the same as the plugins in the plugin manager') + + def hook_import_menu_with_disabled_plugin_test(self): + """ + Test running the hook_import_menu() method with a disabled plugin + """ + # GIVEN: A PluginManager instance and a list with a mocked up plugin whose status is set to Disabled + mocked_plugin = MagicMock() + mocked_plugin.status = PluginStatus.Disabled + mocked_import_menu = MagicMock() + plugin_manager = PluginManager('') + plugin_manager.plugins = [mocked_plugin] + + # WHEN: We run hook_import_menu() + plugin_manager.hook_import_menu(mocked_import_menu) + + # THEN: The createMediaManagerItem() method should have been called + assert mocked_plugin.addImportMenuItem.call_count == 0, \ + u'The addImportMenuItem() method should not have been called.' + + def hook_import_menu_with_active_plugin_test(self): + """ + Test running the hook_import_menu() method with an active plugin + """ + # GIVEN: A PluginManager instance and a list with a mocked up plugin whose status is set to Active + mocked_plugin = MagicMock() + mocked_plugin.status = PluginStatus.Active + mocked_import_menu = MagicMock() + plugin_manager = PluginManager('') + plugin_manager.plugins = [mocked_plugin] + + # WHEN: We run hook_import_menu() + plugin_manager.hook_import_menu(mocked_import_menu) + + # THEN: The addImportMenuItem() method should have been called + mocked_plugin.addImportMenuItem.assert_called_with(mocked_import_menu) + + def hook_export_menu_with_disabled_plugin_test(self): + """ + Test running the hook_export_menu() method with a disabled plugin + """ + # GIVEN: A PluginManager instance and a list with a mocked up plugin whose status is set to Disabled + mocked_plugin = MagicMock() + mocked_plugin.status = PluginStatus.Disabled + mocked_export_menu = MagicMock() + plugin_manager = PluginManager('') + plugin_manager.plugins = [mocked_plugin] + + # WHEN: We run hook_export_menu() + plugin_manager.hook_export_menu(mocked_export_menu) + + # THEN: The addExportMenuItem() method should have been called + assert mocked_plugin.addExportMenuItem.call_count == 0, \ + u'The addExportMenuItem() method should not have been called.' + + def hook_export_menu_with_active_plugin_test(self): + """ + Test running the hook_export_menu() method with an active plugin + """ + # GIVEN: A PluginManager instance and a list with a mocked up plugin whose status is set to Active + mocked_plugin = MagicMock() + mocked_plugin.status = PluginStatus.Active + mocked_export_menu = MagicMock() + plugin_manager = PluginManager('') + plugin_manager.plugins = [mocked_plugin] + + # WHEN: We run hook_export_menu() + plugin_manager.hook_export_menu(mocked_export_menu) + + # THEN: The addExportMenuItem() method should have been called + mocked_plugin.addExportMenuItem.assert_called_with(mocked_export_menu) + + def hook_tools_menu_with_disabled_plugin_test(self): + """ + Test running the hook_tools_menu() method with a disabled plugin + """ + # GIVEN: A PluginManager instance and a list with a mocked up plugin whose status is set to Disabled + mocked_plugin = MagicMock() + mocked_plugin.status = PluginStatus.Disabled + mocked_tools_menu = MagicMock() + plugin_manager = PluginManager('') + plugin_manager.plugins = [mocked_plugin] + + # WHEN: We run hook_tools_menu() + plugin_manager.hook_tools_menu(mocked_tools_menu) + + # THEN: The addToolsMenuItem() method should have been called + assert mocked_plugin.addToolsMenuItem.call_count == 0, \ + u'The addToolsMenuItem() method should not have been called.' + + def hook_tools_menu_with_active_plugin_test(self): + """ + Test running the hook_tools_menu() method with an active plugin + """ + # GIVEN: A PluginManager instance and a list with a mocked up plugin whose status is set to Active + mocked_plugin = MagicMock() + mocked_plugin.status = PluginStatus.Active + mocked_tools_menu = MagicMock() + plugin_manager = PluginManager('') + plugin_manager.plugins = [mocked_plugin] + + # WHEN: We run hook_tools_menu() + plugin_manager.hook_tools_menu(mocked_tools_menu) + + # THEN: The addToolsMenuItem() method should have been called + mocked_plugin.addToolsMenuItem.assert_called_with(mocked_tools_menu) + + def initialise_plugins_with_disabled_plugin_test(self): + """ + Test running the initialise_plugins() method with a disabled plugin + """ + # GIVEN: A PluginManager instance and a list with a mocked up plugin whose status is set to Disabled + mocked_plugin = MagicMock() + mocked_plugin.status = PluginStatus.Disabled + mocked_plugin.isActive.return_value = False + plugin_manager = PluginManager('') + plugin_manager.plugins = [mocked_plugin] + + # WHEN: We run initialise_plugins() + plugin_manager.initialise_plugins() + + # THEN: The isActive() method should have been called, and initialise() method should NOT have been called + mocked_plugin.isActive.assert_called_with() + assert mocked_plugin.initialise.call_count == 0, u'The initialise() method should not have been called.' + + def initialise_plugins_with_active_plugin_test(self): + """ + Test running the initialise_plugins() method with an active plugin + """ + # GIVEN: A PluginManager instance and a list with a mocked up plugin whose status is set to Active + mocked_plugin = MagicMock() + mocked_plugin.status = PluginStatus.Active + mocked_plugin.isActive.return_value = True + plugin_manager = PluginManager('') + plugin_manager.plugins = [mocked_plugin] + + # WHEN: We run initialise_plugins() + plugin_manager.initialise_plugins() + + # THEN: The isActive() and initialise() methods should have been called + mocked_plugin.isActive.assert_called_with() + mocked_plugin.initialise.assert_called_with() + + def finalise_plugins_with_disabled_plugin_test(self): + """ + Test running the finalise_plugins() method with a disabled plugin + """ + # GIVEN: A PluginManager instance and a list with a mocked up plugin whose status is set to Disabled + mocked_plugin = MagicMock() + mocked_plugin.status = PluginStatus.Disabled + mocked_plugin.isActive.return_value = False + plugin_manager = PluginManager('') + plugin_manager.plugins = [mocked_plugin] + + # WHEN: We run finalise_plugins() + plugin_manager.finalise_plugins() + + # THEN: The isActive() method should have been called, and initialise() method should NOT have been called + mocked_plugin.isActive.assert_called_with() + assert mocked_plugin.finalise.call_count == 0, u'The finalise() method should not have been called.' + + def finalise_plugins_with_active_plugin_test(self): + """ + Test running the finalise_plugins() method with an active plugin + """ + # GIVEN: A PluginManager instance and a list with a mocked up plugin whose status is set to Active + mocked_plugin = MagicMock() + mocked_plugin.status = PluginStatus.Active + mocked_plugin.isActive.return_value = True + plugin_manager = PluginManager('') + plugin_manager.plugins = [mocked_plugin] + + # WHEN: We run finalise_plugins() + plugin_manager.finalise_plugins() + + # THEN: The isActive() and finalise() methods should have been called + mocked_plugin.isActive.assert_called_with() + mocked_plugin.finalise.assert_called_with() + + def get_plugin_by_name_does_not_exist_test(self): + """ + Test running the get_plugin_by_name() method to find a plugin that does not exist + """ + # GIVEN: A PluginManager instance and a list with a mocked up plugin whose status is set to Active + mocked_plugin = MagicMock() + mocked_plugin.name = 'Mocked Plugin' + plugin_manager = PluginManager('') + plugin_manager.plugins = [mocked_plugin] + + # WHEN: We run finalise_plugins() + result = plugin_manager.get_plugin_by_name('Missing Plugin') + + # THEN: The isActive() and finalise() methods should have been called + self.assertIsNone(result, u'The result for get_plugin_by_name should be None') + + def get_plugin_by_name_exists_test(self): + """ + Test running the get_plugin_by_name() method to find a plugin that exists + """ + # GIVEN: A PluginManager instance and a list with a mocked up plugin whose status is set to Active + mocked_plugin = MagicMock() + mocked_plugin.name = 'Mocked Plugin' + plugin_manager = PluginManager('') + plugin_manager.plugins = [mocked_plugin] + + # WHEN: We run finalise_plugins() + result = plugin_manager.get_plugin_by_name('Mocked Plugin') + + # THEN: The isActive() and finalise() methods should have been called + self.assertEqual(result, mocked_plugin, u'The result for get_plugin_by_name should be the mocked plugin') + + def new_service_created_with_disabled_plugin_test(self): + """ + Test running the new_service_created() method with a disabled plugin + """ + # GIVEN: A PluginManager instance and a list with a mocked up plugin whose status is set to Disabled + mocked_plugin = MagicMock() + mocked_plugin.status = PluginStatus.Disabled + mocked_plugin.isActive.return_value = False + plugin_manager = PluginManager('') + plugin_manager.plugins = [mocked_plugin] + + # WHEN: We run finalise_plugins() + plugin_manager.new_service_created() + + # THEN: The isActive() method should have been called, and initialise() method should NOT have been called + mocked_plugin.isActive.assert_called_with() + assert mocked_plugin.new_service_created.call_count == 0,\ + u'The new_service_created() method should not have been called.' + + def new_service_created_with_active_plugin_test(self): + """ + Test running the new_service_created() method with an active plugin + """ + # GIVEN: A PluginManager instance and a list with a mocked up plugin whose status is set to Active + mocked_plugin = MagicMock() + mocked_plugin.status = PluginStatus.Active + mocked_plugin.isActive.return_value = True + plugin_manager = PluginManager('') + plugin_manager.plugins = [mocked_plugin] + + # WHEN: We run new_service_created() + plugin_manager.new_service_created() + + # THEN: The isActive() and finalise() methods should have been called + mocked_plugin.isActive.assert_called_with() + mocked_plugin.new_service_created.assert_called_with() diff --git a/tests/functional/openlp_core_lib/test_registry.py b/tests/functional/openlp_core_lib/test_registry.py index f27eef3d8..17fe561d7 100644 --- a/tests/functional/openlp_core_lib/test_registry.py +++ b/tests/functional/openlp_core_lib/test_registry.py @@ -1,13 +1,15 @@ """ - Package to test the openlp.core.lib package. +Package to test the openlp.core.lib package. """ import os - from unittest import TestCase + from mock import MagicMock + from openlp.core.lib import Registry -TESTPATH = os.path.abspath(os.path.join(os.path.dirname(__file__), u'..', u'..', u'resources')) +TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), u'..', u'..', u'resources')) + class TestRegistry(TestCase): From 42e0eea6e7ed96c6a6d0405dcb2c7879139afeca Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Mon, 11 Feb 2013 15:46:08 +0200 Subject: [PATCH 4/5] Tidy up a little. --- openlp/core/lib/pluginmanager.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/openlp/core/lib/pluginmanager.py b/openlp/core/lib/pluginmanager.py index cdd99a9e0..aefb11fc1 100644 --- a/openlp/core/lib/pluginmanager.py +++ b/openlp/core/lib/pluginmanager.py @@ -72,16 +72,14 @@ class PluginManager(object): """ log.info(u'Finding plugins') start_depth = len(os.path.abspath(plugin_dir).split(os.sep)) + present_plugin_dir = os.path.join(plugin_dir, 'presentations') log.debug(u'finding plugins in %s at depth %d', unicode(plugin_dir), start_depth) for root, dirs, files in os.walk(plugin_dir): - # TODO Presentation plugin is not yet working on Mac OS X. - # For now just ignore it. The following code will hide it - # in settings dialog. - if sys.platform == 'darwin': - present_plugin_dir = os.path.join(plugin_dir, 'presentations') - # Ignore files from the presentation plugin directory. - if root.startswith(present_plugin_dir): - continue + if sys.platform == 'darwin'and root.startswith(present_plugin_dir): + # TODO Presentation plugin is not yet working on Mac OS X. + # For now just ignore it. The following code will ignore files from the presentation plugin directory + # and thereby never import the plugin. + continue for name in files: if name.endswith(u'.py') and not name.startswith(u'__'): path = os.path.abspath(os.path.join(root, name)) From b5f3e46ad451296ee151b1b6dec641675f244897 Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Mon, 11 Feb 2013 19:41:32 +0200 Subject: [PATCH 5/5] Pedantics. --- openlp/core/lib/pluginmanager.py | 7 +++---- tests/functional/openlp_core_lib/test_pluginmanager.py | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/openlp/core/lib/pluginmanager.py b/openlp/core/lib/pluginmanager.py index aefb11fc1..d248469c1 100644 --- a/openlp/core/lib/pluginmanager.py +++ b/openlp/core/lib/pluginmanager.py @@ -93,13 +93,12 @@ class PluginManager(object): try: # Use the "imp" library to try to get around a problem with the PyUNO library which # monkey-patches the __import__ function to do some magic. This causes issues with our tests. - # First, try to find the module we want to import, searching the directory in ``root`` + # First, try to find the module we want to import, searching the directory in root fp, path_name, description = imp.find_module(module_name, [root]) - # Then load the module (do the actual import) using the details from ``find_module()`` + # Then load the module (do the actual import) using the details from find_module() imp.load_module(module_name, fp, path_name, description) except ImportError, e: - log.exception(u'Failed to import module %s on path %s for reason %s', - module_name, path, e.args[0]) + log.exception(u'Failed to import module %s on path %s: %s', module_name, path, e.args[0]) plugin_classes = Plugin.__subclasses__() plugin_objects = [] for p in plugin_classes: diff --git a/tests/functional/openlp_core_lib/test_pluginmanager.py b/tests/functional/openlp_core_lib/test_pluginmanager.py index 3539373e0..bad38d721 100644 --- a/tests/functional/openlp_core_lib/test_pluginmanager.py +++ b/tests/functional/openlp_core_lib/test_pluginmanager.py @@ -89,7 +89,7 @@ class TestPluginManager(TestCase): assert mocked_plugin.createSettingsTab.call_count == 0, \ u'The createMediaManagerItem() method should not have been called.' self.assertEqual(mocked_settings_form.plugins, plugin_manager.plugins, - u'The plugins on the settings form should be the same as the plugins in the plugin manager') + u'The plugins on the settings form should be the same as the plugins in the plugin manager') def hook_settings_tabs_with_active_plugin_and_no_form_test(self): """