summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2015-02-22 21:55:08 -0500
committerNed Batchelder <ned@nedbatchelder.com>2015-02-22 21:55:08 -0500
commitae8870bf5732895c1e68c6f64268a775a617f403 (patch)
treeeb3da03b7120f1c65f5ba4666e57d935b92b39b1
parent60f6763320d19a317495495ffddd8327b585bf6a (diff)
downloadpython-coveragepy-ae8870bf5732895c1e68c6f64268a775a617f403.tar.gz
Ensure all FileReporter's have a .name attribute
-rw-r--r--coverage/control.py20
-rw-r--r--tests/plugin2.py8
-rw-r--r--tests/test_plugins.py72
3 files changed, 88 insertions, 12 deletions
diff --git a/coverage/control.py b/coverage/control.py
index 2db5802..2c0d9ed 100644
--- a/coverage/control.py
+++ b/coverage/control.py
@@ -18,7 +18,7 @@ from coverage.data import CoverageData
from coverage.debug import DebugControl
from coverage.files import FileLocator, TreeMatcher, FnmatchMatcher
from coverage.files import PathAliases, find_python_files, prep_patterns
-from coverage.files import ModuleMatcher
+from coverage.files import ModuleMatcher, abs_file
from coverage.html import HtmlReporter
from coverage.misc import CoverageException, bool_or_none, join_regex
from coverage.misc import file_be_gone, overrides
@@ -837,12 +837,13 @@ class Coverage(object):
plugin = None
if isinstance(morf, string_class):
- plugin_name = self.data.plugin_data().get(morf)
+ abs_morf = abs_file(morf)
+ plugin_name = self.data.plugin_data().get(abs_morf)
if plugin_name:
plugin = self.plugins.get(plugin_name)
if plugin:
- file_reporter = plugin.file_reporter(morf)
+ file_reporter = plugin.file_reporter(abs_morf)
if file_reporter is None:
raise CoverageException(
"Plugin %r did not provide a file reporter for %r." % (
@@ -852,6 +853,13 @@ class Coverage(object):
else:
file_reporter = PythonFileReporter(morf, self)
+ # The FileReporter can have a name attribute, but if it doesn't, we'll
+ # supply it as the relative path to self.filename.
+ if not hasattr(file_reporter, "name"):
+ file_reporter.name = self.file_locator.relative_filename(
+ file_reporter.filename
+ )
+
return file_reporter
def _get_file_reporters(self, morfs=None):
@@ -889,9 +897,9 @@ class Coverage(object):
Each module in `morfs` is listed, with counts of statements, executed
statements, missing statements, and a list of lines missed.
- `include` is a list of filename patterns. Modules whose filenames
- match those patterns will be included in the report. Modules matching
- `omit` will not be included in the report.
+ `include` is a list of filename patterns. Files that match will be
+ included in the report. Files matching `omit` will not be included in
+ the report.
Returns a float, the total percentage covered.
diff --git a/tests/plugin2.py b/tests/plugin2.py
index 9d47d26..658ee22 100644
--- a/tests/plugin2.py
+++ b/tests/plugin2.py
@@ -1,5 +1,7 @@
"""A plugin for test_plugins.py to import."""
+import os.path
+
import coverage
# pylint: disable=missing-docstring
@@ -23,16 +25,16 @@ class RenderFileTracer(coverage.plugin.FileTracer):
def dynamic_source_filename(self, filename, frame):
if frame.f_code.co_name != "render":
return None
- return frame.f_locals['filename']
+ return os.path.abspath(frame.f_locals['filename'])
def line_number_range(self, frame):
lineno = frame.f_locals['linenum']
- return lineno,lineno+1
+ return lineno, lineno+1
class FileReporter(coverage.plugin.FileReporter):
def statements(self):
# Goofy test arrangement: claim that the file has as many lines as the
# number in its name.
- num = self.filename.split(".")[0].split("_")[1]
+ num = os.path.basename(self.filename).split(".")[0].split("_")[1]
return set(range(1, int(num)+1))
diff --git a/tests/test_plugins.py b/tests/test_plugins.py
index 2d12a3c..88c653c 100644
--- a/tests/test_plugins.py
+++ b/tests/test_plugins.py
@@ -316,9 +316,18 @@ class GoodPluginTest(FileTracerTest):
# In Python 2, either kind of string should be OK.
if sys.version_info[0] == 2:
- assert render(u"unicode_3.html", 2) == "[unicode_3.html @ 2]"
+ assert render(u"uni_3.html", 2) == "[uni_3.html @ 2]"
""")
+ # will try to read the actual source files, so make some
+ # source files.
+ def lines(n):
+ """Make a string with n lines of text."""
+ return "".join("line %d\n" % i for i in range(n))
+
+ self.make_file("bar_4.html", lines(4))
+ self.make_file("foo_7.html", lines(7))
+
def test_plugin2(self):
self.make_render_and_caller()
@@ -345,10 +354,10 @@ class GoodPluginTest(FileTracerTest):
self.assertNotIn("quux_5.html", cov.data.summary())
if env.PY2:
- _, statements, missing, _ = cov.analysis("unicode_3.html")
+ _, statements, missing, _ = cov.analysis("uni_3.html")
self.assertEqual(statements, [1, 2, 3])
self.assertEqual(missing, [1])
- self.assertIn("unicode_3.html", cov.data.summary())
+ self.assertIn("uni_3.html", cov.data.summary())
def test_plugin2_with_branch(self):
self.make_render_and_caller()
@@ -371,6 +380,63 @@ class GoodPluginTest(FileTracerTest):
self.assertEqual(analysis.missing, set([1, 2, 3, 6, 7]))
+ def test_plugin2_with_text_report(self):
+ self.make_render_and_caller()
+
+ cov = coverage.Coverage(branch=True, omit=["*quux*"])
+ cov.config["run:plugins"] = ["tests.plugin2"]
+
+ self.start_import_stop(cov, "caller")
+
+ repout = StringIO()
+ total = cov.report(file=repout, include=["*.html"], omit=["uni*.html"])
+ report = repout.getvalue().splitlines()
+ expected = [
+ 'Name Stmts Miss Branch BrPart Cover Missing',
+ '--------------------------------------------------------',
+ 'bar_4.html 4 2 0 0 50% 1, 4',
+ 'foo_7.html 7 5 0 0 29% 1-3, 6-7',
+ '--------------------------------------------------------',
+ 'TOTAL 11 7 0 0 36% ',
+ ]
+ self.assertEqual(report, expected)
+ self.assertAlmostEqual(total, 36.36, places=2)
+
+ def test_plugin2_with_html_report(self):
+ self.make_render_and_caller()
+
+ cov = coverage.Coverage(branch=True, omit=["*quux*"])
+ cov.config["run:plugins"] = ["tests.plugin2"]
+
+ self.start_import_stop(cov, "caller")
+
+ total = cov.html_report(include=["*.html"], omit=["uni*.html"])
+ self.assertAlmostEqual(total, 36.36, places=2)
+
+ self.assert_exists("htmlcov/index.html")
+ self.assert_exists("htmlcov/bar_4_html.html")
+ self.assert_exists("htmlcov/foo_7_html.html")
+
+ def test_plugin2_with_xml_report(self):
+ self.make_render_and_caller()
+
+ cov = coverage.Coverage(branch=True, omit=["*quux*"])
+ cov.config["run:plugins"] = ["tests.plugin2"]
+
+ self.start_import_stop(cov, "caller")
+
+ total = cov.xml_report(include=["*.html"], omit=["uni*.html"])
+ self.assertAlmostEqual(total, 36.36, places=2)
+
+ with open("coverage.xml") as fxml:
+ xml = fxml.read()
+
+ for snip in [
+ 'filename="bar_4.html" line-rate="0.5" name="bar_4.html"',
+ 'filename="foo_7.html" line-rate="0.2857" name="foo_7.html"',
+ ]:
+ self.assertIn(snip, xml)
+
class BadPluginTest(FileTracerTest):
"""Test error handling around plugins."""