diff options
-rw-r--r-- | AUTHORS.txt | 1 | ||||
-rw-r--r-- | CHANGES.txt | 5 | ||||
-rw-r--r-- | coverage/config.py | 2 | ||||
-rw-r--r-- | coverage/xmlreport.py | 2 | ||||
-rw-r--r-- | tests/test_config.py | 2 | ||||
-rw-r--r-- | tests/test_xml.py | 94 |
6 files changed, 88 insertions, 18 deletions
diff --git a/AUTHORS.txt b/AUTHORS.txt index 5e7bb54..f2d561e 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -7,6 +7,7 @@ Marc Abramowitz Chris Adams Danny Allen Geoff Bache +Lex Berezhny Julian Berman Titus Brown Brett Cannon diff --git a/CHANGES.txt b/CHANGES.txt index 7bd3bd6..4e801ff 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -14,6 +14,11 @@ Latest regression, I apologize. This was reported in `issue 235`_, which is now fixed. +- A new configuration option for the XML report: ``[xml] package_depth`` + controls which directories are identified as packages in the report. + Directories deeper than this depth are not reported as packages. + Thanks, Lex Berezhny. + - When looking for the source for a frame, check if the file exists. On Windows, .pyw files are no longer recorded as .py files. Along the way, this fixed `issue 290`_. diff --git a/coverage/config.py b/coverage/config.py index 326389c..7b14267 100644 --- a/coverage/config.py +++ b/coverage/config.py @@ -183,6 +183,7 @@ class CoverageConfig(object): # Defaults for [xml] self.xml_output = "coverage.xml" + self.xml_package_depth = 99 # Defaults for [paths] self.paths = {} @@ -283,6 +284,7 @@ class CoverageConfig(object): # [xml] ('xml_output', 'xml:output'), + ('xml_package_depth', 'xml:package_depth', 'int'), ] def _set_attr_from_config_option(self, cp, attr, where, type_=''): diff --git a/coverage/xmlreport.py b/coverage/xmlreport.py index 3510c5b..f7ad2b8 100644 --- a/coverage/xmlreport.py +++ b/coverage/xmlreport.py @@ -124,6 +124,8 @@ class XmlReporter(Reporter): filename = cu.file_locator.relative_filename(cu.filename) filename = filename.replace("\\", "/") dirname = os.path.dirname(filename) or "." + parts = dirname.split("/") + dirname = "/".join(parts[:self.config.xml_package_depth]) package_name = dirname.replace("/", ".") className = cu.name diff --git a/tests/test_config.py b/tests/test_config.py index 450c94f..366b4bc 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -233,6 +233,7 @@ class ConfigFileTest(CoverageTest): title = Title & nums # nums! [{section}xml] output=mycov.xml + package_depth = 17 [{section}paths] source = @@ -294,6 +295,7 @@ class ConfigFileTest(CoverageTest): self.assertEqual(cov.config.html_title, "Title & nums # nums!") self.assertEqual(cov.config.xml_output, "mycov.xml") + self.assertEqual(cov.config.xml_package_depth, 17) self.assertEqual(cov.config.paths, { 'source': ['.', '/home/ned/src/'], diff --git a/tests/test_xml.py b/tests/test_xml.py index 5309ebc..d7611eb 100644 --- a/tests/test_xml.py +++ b/tests/test_xml.py @@ -140,30 +140,88 @@ class XmlReportTest(XmlTestHelpers, CoverageTest): class XmlPackageStructureTest(XmlTestHelpers, CoverageTest): """Tests about the package structure reported in the coverage.xml file.""" - def test_packages(self): + def package_and_class_tags(self, cov): + """Run an XML report on `cov`, and get the package and class tags.""" + self.captured_stdout.truncate(0) + cov.xml_report(outfile="-") + packages_and_classes = re_lines(self.stdout(), r"<package |<class ") + scrubs = r' branch-rate="0"| complexity="0"| line-rate="[\d.]+"' + return clean("".join(packages_and_classes), scrubs) + + def assert_package_and_class_tags(self, cov, result): + """Check the XML package and class tags from `cov` match `result`.""" + self.assertMultiLineEqual( + self.package_and_class_tags(cov), + clean(result) + ) + + def test_package_names(self): self.make_tree(width=1, depth=3) self.make_file("main.py", """\ from d0.d0 import f0 """) cov = coverage.coverage(source=".") self.start_import_stop(cov, "main") - cov.xml_report(outfile="-") - xml = self.stdout() - packages_and_classes = "".join(re_lines(xml, r"<package |<class ")) - scrubs = r' branch-rate="0"| complexity="0"| line-rate="[\d.]+"' - self.assertMultiLineEqual( - clean(packages_and_classes, scrubs), - clean("""\ - <package name="."> - <class filename="main.py" name="main.py"> - <package name="d0"> - <class filename="d0/__init__.py" name="__init__.py"> - <class filename="d0/f0.py" name="f0.py"> - <package name="d0.d0"> - <class filename="d0/d0/__init__.py" name="__init__.py"> - <class filename="d0/d0/f0.py" name="f0.py"> - """) - ) + self.assert_package_and_class_tags(cov, """\ + <package name="."> + <class filename="main.py" name="main.py"> + <package name="d0"> + <class filename="d0/__init__.py" name="__init__.py"> + <class filename="d0/f0.py" name="f0.py"> + <package name="d0.d0"> + <class filename="d0/d0/__init__.py" name="__init__.py"> + <class filename="d0/d0/f0.py" name="f0.py"> + """) + + def test_package_depth(self): + self.make_tree(width=1, depth=4) + self.make_file("main.py", """\ + from d0.d0 import f0 + """) + cov = coverage.coverage(source=".") + self.start_import_stop(cov, "main") + + cov.config["xml:package_depth"] = 1 + self.assert_package_and_class_tags(cov, """\ + <package name="."> + <class filename="main.py" name="main.py"> + <package name="d0"> + <class filename="d0/__init__.py" name="__init__.py"> + <class filename="d0/d0/__init__.py" name="d0/__init__.py"> + <class filename="d0/d0/d0/__init__.py" name="d0/d0/__init__.py"> + <class filename="d0/d0/d0/f0.py" name="d0/d0/f0.py"> + <class filename="d0/d0/f0.py" name="d0/f0.py"> + <class filename="d0/f0.py" name="f0.py"> + """) + + cov.config["xml:package_depth"] = 2 + self.assert_package_and_class_tags(cov, """\ + <package name="."> + <class filename="main.py" name="main.py"> + <package name="d0"> + <class filename="d0/__init__.py" name="__init__.py"> + <class filename="d0/f0.py" name="f0.py"> + <package name="d0.d0"> + <class filename="d0/d0/__init__.py" name="__init__.py"> + <class filename="d0/d0/d0/__init__.py" name="d0/__init__.py"> + <class filename="d0/d0/d0/f0.py" name="d0/f0.py"> + <class filename="d0/d0/f0.py" name="f0.py"> + """) + + cov.config["xml:package_depth"] = 3 + self.assert_package_and_class_tags(cov, """\ + <package name="."> + <class filename="main.py" name="main.py"> + <package name="d0"> + <class filename="d0/__init__.py" name="__init__.py"> + <class filename="d0/f0.py" name="f0.py"> + <package name="d0.d0"> + <class filename="d0/d0/__init__.py" name="__init__.py"> + <class filename="d0/d0/f0.py" name="f0.py"> + <package name="d0.d0.d0"> + <class filename="d0/d0/d0/__init__.py" name="__init__.py"> + <class filename="d0/d0/d0/f0.py" name="f0.py"> + """) def re_lines(text, pat): |