diff options
author | Ned Batchelder <ned@nedbatchelder.com> | 2010-09-03 23:15:20 -0400 |
---|---|---|
committer | Ned Batchelder <ned@nedbatchelder.com> | 2010-09-03 23:15:20 -0400 |
commit | 8153341439f1eddddad18ee6ca8ca10a88549129 (patch) | |
tree | d9e6c8a5d9c7e642157a2bf15e1d7a659969c843 | |
parent | 9da5c35a04dd117dda5f868ab1057b2f0603708b (diff) | |
download | python-coveragepy-git-8153341439f1eddddad18ee6ca8ca10a88549129.tar.gz |
Now completely unexecuted source files can be included in reporting. Specifying --source tells coverage.py where to search for files that haven't been executed.
-rw-r--r-- | CHANGES.txt | 4 | ||||
-rw-r--r-- | coverage/control.py | 7 | ||||
-rw-r--r-- | coverage/data.py | 4 | ||||
-rw-r--r-- | doc/source.rst | 5 | ||||
-rw-r--r-- | test/test_api.py | 5 | ||||
-rw-r--r-- | test/test_data.py | 6 |
6 files changed, 29 insertions, 2 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index cca83310..62336f6b 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -6,6 +6,10 @@ Change history for Coverage.py Version 3.4b2 ------------- +- Completely unexecuted files can now be included in coverage results, reported + as 0% covered. This only happens if the --source option is specified, since + coverage.py needs guidance about where to look for source files. + - Coverage percentages are now displayed uniformly across reporting methods. A percentage is only reported as 0% or 100% if they are truly 0 or 100, and are rounded otherwise. Fixes `issue 41` and issue 70`. diff --git a/coverage/control.py b/coverage/control.py index dd7d705b..28c8850f 100644 --- a/coverage/control.py +++ b/coverage/control.py @@ -9,6 +9,7 @@ from coverage.collector import Collector from coverage.config import CoverageConfig from coverage.data import CoverageData from coverage.files import FileLocator, TreeMatcher, FnmatchMatcher +from coverage.files import find_python_files from coverage.html import HtmlReporter from coverage.misc import CoverageException, bool_or_none from coverage.results import Analysis, Numbers @@ -303,6 +304,7 @@ class coverage(object): else: pkg_file = self._source_for_file(pkg_file) pkg_file = self.file_locator.canonical_filename(pkg_file) + self.source.append(pkg_file) self.source_match.add(pkg_file) for pkg in found: @@ -437,6 +439,11 @@ class coverage(object): if not summary: self._warn("No data was collected.") + # Find files that were never executed at all. + for src in self.source: + for py_file in find_python_files(src): + self.data.touch_file(py_file) + self._harvested = True # Backward compatibility with version 1. diff --git a/coverage/data.py b/coverage/data.py index 6d49f710..30119d9c 100644 --- a/coverage/data.py +++ b/coverage/data.py @@ -207,6 +207,10 @@ class CoverageData(object): for filename, arcs in arc_data.items(): self.arcs.setdefault(filename, {}).update(arcs) + def touch_file(self, filename): + """Ensure that `filename` appears in the data, empty if needed.""" + self.lines.setdefault(filename, {}) + def executed_files(self): """A list of all files that had been measured as executed.""" return list(self.lines.keys()) diff --git a/doc/source.rst b/doc/source.rst index e39090a4..3f0a1566 100644 --- a/doc/source.rst +++ b/doc/source.rst @@ -28,7 +28,9 @@ all code, unless it is part of the Python standard library. You can specify source to measure with the ``--source`` command-line switch, or the ``[run] source`` configuration value. The value is a list of directories or package names. If specified, only source inside these directories or -packages will be measured. +packages will be measured. Specifying the source option also enables +coverage.py to report on unexecuted files, since it can search the source tree +for files that haven't been measured at all. You can further fine-tune coverage.py's attention with the ``--include`` and ``--omit`` switches (or ``[run] include`` and ``[run] omit`` configuration @@ -72,4 +74,3 @@ reporting. Note that these are ways of specifying files to measure. You can also exclude individual source lines. See :ref:`excluding` for details. - diff --git a/test/test_api.py b/test/test_api.py index aa6f42cd..5952dfe7 100644 --- a/test/test_api.py +++ b/test/test_api.py @@ -324,6 +324,8 @@ class SourceOmitIncludeTest(CoverageTest): self.assertEqual(lines['p1b.py'], 3) self.assertEqual(lines['p2a.py'], 3) self.assertEqual(lines['p2b.py'], 3) + # Because there was no source= specified, we don't search for + # unexecuted files. self.assert_('p1c.py' not in lines) def test_source_package(self): @@ -332,6 +334,8 @@ class SourceOmitIncludeTest(CoverageTest): self.assertEqual(lines['p1b.py'], 3) self.assert_('p2a.py' not in lines) self.assert_('p2b.py' not in lines) + # Because source= was specified, we do search for unexecuted files. + self.assertEqual(lines['p1c.py'], 0) def test_source_package_dotted(self): lines = self.coverage_usepkgs_summary(source=["pkg1.p1b"]) @@ -339,6 +343,7 @@ class SourceOmitIncludeTest(CoverageTest): self.assertEqual(lines['p1b.py'], 3) self.assert_('p2a.py' not in lines) self.assert_('p2b.py' not in lines) + self.assert_('p1c.py' not in lines) def test_include(self): lines = self.coverage_usepkgs_summary(include=["*/p1a.py"]) diff --git a/test/test_data.py b/test/test_data.py index 83a5b8ae..fd7e4878 100644 --- a/test/test_data.py +++ b/test/test_data.py @@ -45,6 +45,12 @@ class DataTest(CoverageTest): self.assert_summary(covdata, SUMMARY_1) self.assert_executed_files(covdata, EXECED_FILES_1) + def test_touch_file(self): + covdata = CoverageData() + covdata.add_line_data(DATA_1) + covdata.touch_file('x.py') + self.assert_executed_files(covdata, EXECED_FILES_1 + ['x.py']) + def test_writing_and_reading(self): covdata1 = CoverageData() covdata1.add_line_data(DATA_1) |