diff options
Diffstat (limited to 'tests/test_plugins.py')
-rw-r--r-- | tests/test_plugins.py | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/tests/test_plugins.py b/tests/test_plugins.py new file mode 100644 index 00000000..9c5a037d --- /dev/null +++ b/tests/test_plugins.py @@ -0,0 +1,217 @@ +"""Tests for plugins.""" + +import os.path + +import coverage +from coverage.codeunit import CodeUnit +from coverage.parser import CodeParser +from coverage.plugin import Plugins, overrides + +from tests.coveragetest import CoverageTest + + +class FakeConfig(object): + """A fake config for use in tests.""" + + def __init__(self, plugin, options): + self.plugin = plugin + self.options = options + self.asked_for = [] + + def get_plugin_options(self, module): + """Just return the options for `module` if this is the right module.""" + self.asked_for.append(module) + if module == self.plugin: + return self.options + else: + return {} + + +class PluginUnitTest(CoverageTest): + """Test Plugins.load_plugins directly.""" + + def test_importing_and_configuring(self): + self.make_file("plugin1.py", """\ + from coverage import CoveragePlugin + + class Plugin(CoveragePlugin): + def __init__(self, options): + super(Plugin, self).__init__(options) + self.this_is = "me" + """) + + config = FakeConfig("plugin1", {'a':'hello'}) + plugins = list(Plugins.load_plugins(["plugin1"], config)) + + self.assertEqual(len(plugins), 1) + self.assertEqual(plugins[0].this_is, "me") + self.assertEqual(plugins[0].options, {'a':'hello'}) + self.assertEqual(config.asked_for, ['plugin1']) + + def test_importing_and_configuring_more_than_one(self): + self.make_file("plugin1.py", """\ + from coverage import CoveragePlugin + + class Plugin(CoveragePlugin): + def __init__(self, options): + super(Plugin, self).__init__(options) + self.this_is = "me" + """) + self.make_file("plugin2.py", """\ + from coverage import CoveragePlugin + + class Plugin(CoveragePlugin): + pass + """) + + config = FakeConfig("plugin1", {'a':'hello'}) + plugins = list(Plugins.load_plugins(["plugin1", "plugin2"], config)) + + self.assertEqual(len(plugins), 2) + self.assertEqual(plugins[0].this_is, "me") + self.assertEqual(plugins[0].options, {'a':'hello'}) + self.assertEqual(plugins[1].options, {}) + self.assertEqual(config.asked_for, ['plugin1', 'plugin2']) + + def test_cant_import(self): + with self.assertRaises(ImportError): + _ = Plugins.load_plugins(["plugin_not_there"], None) + + def test_ok_to_not_define_plugin(self): + self.make_file("plugin2.py", """\ + from coverage import CoveragePlugin + + Nothing = 0 + """) + plugins = list(Plugins.load_plugins(["plugin2"], None)) + self.assertEqual(plugins, []) + + +class PluginTest(CoverageTest): + """Test plugins through the Coverage class.""" + + def test_plugin_imported(self): + # Prove that a plugin will be imported. + self.make_file("my_plugin.py", """\ + with open("evidence.out", "w") as f: + f.write("we are here!") + """) + + self.assert_doesnt_exist("evidence.out") + _ = coverage.Coverage(plugins=["my_plugin"]) + + with open("evidence.out") as f: + self.assertEqual(f.read(), "we are here!") + + def test_missing_plugin_raises_import_error(self): + # Prove that a missing plugin will raise an ImportError. + with self.assertRaises(ImportError): + cov = coverage.Coverage(plugins=["does_not_exist_woijwoicweo"]) + cov.start() + + def test_bad_plugin_isnt_hidden(self): + # Prove that a plugin with an error in it will raise the error. + self.make_file("plugin_over_zero.py", """\ + 1/0 + """) + with self.assertRaises(ZeroDivisionError): + _ = coverage.Coverage(plugins=["plugin_over_zero"]) + + def test_importing_myself(self): + self.make_file("simple.py", """\ + import try_xyz + a = 1 + b = 2 + """) + self.make_file("try_xyz.py", """\ + c = 3 + d = 4 + """) + + cov = coverage.Coverage(plugins=["tests.test_plugins"]) + + # Import the python file, executing it. + self.start_import_stop(cov, "simple") + + _, statements, missing, _ = cov.analysis("simple.py") + self.assertEqual(statements, [1,2,3]) + self.assertEqual(missing, []) + _, statements, _, _ = cov.analysis("/src/try_ABC.zz") + self.assertEqual(statements, [105, 106, 107, 205, 206, 207]) + + +class Plugin(coverage.CoveragePlugin): + def trace_judge(self, disp): + if "xyz.py" in disp.original_filename: + disp.trace = True + disp.source_filename = os.path.join( + "/src", + os.path.basename( + disp.original_filename.replace("xyz.py", "ABC.zz") + ) + ) + + def line_number_range(self, frame): + lineno = frame.f_lineno + return lineno*100+5, lineno*100+7 + + def code_unit_class(self, filename): + return PluginCodeUnit + +class PluginCodeUnit(CodeUnit): + def get_parser(self, exclude=None): + return PluginParser() + +class PluginParser(CodeParser): + def parse_source(self): + return set([105, 106, 107, 205, 206, 207]), set([]) + + +class OverridesTest(CoverageTest): + """Test plugins.py:overrides.""" + + run_in_temp_dir = False + + def test_overrides(self): + class SomeBase(object): + """Base class, two base methods.""" + def method1(self): + pass + + def method2(self): + pass + + class Derived1(SomeBase): + """Simple single inheritance.""" + def method1(self): + pass + + self.assertTrue(overrides(Derived1(), "method1", SomeBase)) + self.assertFalse(overrides(Derived1(), "method2", SomeBase)) + + class FurtherDerived1(Derived1): + """Derive again from Derived1, inherit its method1.""" + pass + + self.assertTrue(overrides(FurtherDerived1(), "method1", SomeBase)) + self.assertFalse(overrides(FurtherDerived1(), "method2", SomeBase)) + + class FurtherDerived2(Derived1): + """Override the overridden method.""" + def method1(self): + pass + + self.assertTrue(overrides(FurtherDerived2(), "method1", SomeBase)) + self.assertFalse(overrides(FurtherDerived2(), "method2", SomeBase)) + + class Mixin(object): + """A mixin that overrides method1.""" + def method1(self): + pass + + class Derived2(Mixin, SomeBase): + """A class that gets the method from the mixin.""" + pass + + self.assertTrue(overrides(Derived2(), "method1", SomeBase)) + self.assertFalse(overrides(Derived2(), "method2", SomeBase)) |