diff --git a/doc/source/pluginguide.rst b/doc/source/pluginguide.rst index 3cb97d0f8b..57b81267d2 100644 --- a/doc/source/pluginguide.rst +++ b/doc/source/pluginguide.rst @@ -507,6 +507,14 @@ the engine will make them available next time the service starts. See one of the Installation Guides at http://docs.OpenStack.org/ for more information on configuring the orchestration service. +Testing +------- + +Tests can live inside the plug-in under the ``tests`` +namespace/directory. The Heat plug-in loader will implicitly not load +anything under that directory. This is useful when your plug-in tests +have dependencies you don't want installed in production. + Putting It All Together ----------------------- You can find the plugin classes in ``heat/engine/resources``. An diff --git a/heat/common/plugin_loader.py b/heat/common/plugin_loader.py index 59e11da60f..7ca017b9b2 100644 --- a/heat/common/plugin_loader.py +++ b/heat/common/plugin_loader.py @@ -86,6 +86,11 @@ def load_modules(package, ignore_error=False): for importer, module_name, is_package in pkgutil.walk_packages(path, pkg_prefix): + # NOTE(chmouel): Skips tests package or this will try to load + # them when loading plugins. + if '.tests.' in module_name: + continue + try: module = _import_module(importer, module_name, package) except ImportError: diff --git a/heat/tests/test_plugin_loader.py b/heat/tests/test_plugin_loader.py index 04e2ea72cf..74383e6515 100644 --- a/heat/tests/test_plugin_loader.py +++ b/heat/tests/test_plugin_loader.py @@ -15,6 +15,7 @@ import pkgutil import sys +import mock import testtools from heat.common import plugin_loader @@ -64,3 +65,14 @@ class PluginLoaderTest(testtools.TestCase): self.assertIsNone(plugin_loader._import_module(importer, 'wibble', heat.engine)) + + @mock.patch.object(plugin_loader, "_import_module", mock.MagicMock()) + @mock.patch('pkgutil.walk_packages') + def test_load_modules_skip_test(self, mp): + importer = pkgutil.ImpImporter(heat.engine.__path__[0]) + + mp.return_value = ((importer, "hola.foo", None), + (importer, "hola.tests.test_foo", None)) + loaded = plugin_loader.load_modules( + heat.engine, ignore_error=True) + self.assertEqual(1, len(list(loaded))) diff --git a/heat/tests/test_plugin_manager.py b/heat/tests/test_plugin_manager.py index e9011b4231..1b19d61e12 100644 --- a/heat/tests/test_plugin_manager.py +++ b/heat/tests/test_plugin_manager.py @@ -90,10 +90,27 @@ class TestPluginManager(HeatTestCase): self.assertTrue(module.__name__.startswith('heat.tests') or module.__name__.startswith('heat.engine.plugins')) - def test_load_all(self): + def test_load_all_skip_tests(self): mgr = plugin_manager.PluginManager('heat.tests') pm = plugin_manager.PluginMapping('current_test') all_items = pm.load_all(mgr) + + for item in current_test_mapping().iteritems(): + self.assertNotIn(item, all_items) + + def test_load_all(self): + import heat.tests.test_plugin_manager + mgr = plugin_manager.PluginManager('heat.tests') + pm = plugin_manager.PluginMapping('current_test') + + # NOTE(chmou): We force the modules to be ourself so we can get + # the current_test_mapping if not we will would be + # skipped by plugin_loader.load_modules since we are skipping + # the loading of the package with tests in there + mgr.modules = [heat.tests.test_plugin_manager] + + all_items = pm.load_all(mgr) + for item in current_test_mapping().iteritems(): self.assertIn(item, all_items)