diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/conftest.py | 3 | ||||
| -rw-r--r-- | tests/goldtest.py | 19 | ||||
| -rw-r--r-- | tests/test_api.py | 2 | ||||
| -rw-r--r-- | tests/test_arcs.py | 22 | ||||
| -rw-r--r-- | tests/test_data.py | 16 | ||||
| -rw-r--r-- | tests/test_files.py | 13 | ||||
| -rw-r--r-- | tests/test_plugins.py | 28 | ||||
| -rw-r--r-- | tests/test_process.py | 19 | ||||
| -rw-r--r-- | tests/test_templite.py | 18 | ||||
| -rw-r--r-- | tests/test_xml.py | 292 |
10 files changed, 286 insertions, 146 deletions
diff --git a/tests/conftest.py b/tests/conftest.py index c883ef7b..d0572dca 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -16,6 +16,9 @@ import pytest from coverage import env +# Pytest can take additional options: +# $set_env.py: PYTEST_ADDOPTS - Extra arguments to pytest. + @pytest.fixture(autouse=True) def set_warnings(): """Enable DeprecationWarnings during all tests.""" diff --git a/tests/goldtest.py b/tests/goldtest.py index 4c6c3c96..b5e32f5f 100644 --- a/tests/goldtest.py +++ b/tests/goldtest.py @@ -10,6 +10,7 @@ import os import os.path import re import sys +import xml.etree.ElementTree from unittest_mixins import change_dir # pylint: disable=unused-import @@ -79,12 +80,19 @@ def compare( # ourselves. text_diff = [] for f in diff_files: + expected_file = os.path.join(expected_dir, f) - actual_file = os.path.join(actual_dir, f) with open(expected_file, READ_MODE) as fobj: expected = fobj.read() + if expected_file.endswith(".xml"): + expected = canonicalize_xml(expected) + + actual_file = os.path.join(actual_dir, f) with open(actual_file, READ_MODE) as fobj: actual = fobj.read() + if actual_file.endswith(".xml"): + actual = canonicalize_xml(actual) + if scrubs: expected = scrub(expected, scrubs) actual = scrub(actual, scrubs) @@ -102,6 +110,15 @@ def compare( assert not actual_only, "Files in %s only: %s" % (actual_dir, actual_only) +def canonicalize_xml(xtext): + """Canonicalize some XML text.""" + root = xml.etree.ElementTree.fromstring(xtext) + for node in root.iter(): + node.attrib = dict(sorted(node.items())) + xtext = xml.etree.ElementTree.tostring(root) + return xtext.decode('utf8') + + def contains(filename, *strlist): """Check that the file contains all of a list of strings. diff --git a/tests/test_api.py b/tests/test_api.py index 2f6f7a2f..755a89a2 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -495,7 +495,7 @@ class NamespaceModuleTest(UsingModulesMixin, CoverageTest): def setUp(self): super(NamespaceModuleTest, self).setUp() - if env.PYVERSION < (3, 3): + if not env.PYBEHAVIOR.namespaces_pep420: self.skipTest("Python before 3.3 doesn't have namespace packages") def test_explicit_namespace_module(self): diff --git a/tests/test_arcs.py b/tests/test_arcs.py index d3430af2..cbbac64a 100644 --- a/tests/test_arcs.py +++ b/tests/test_arcs.py @@ -1056,7 +1056,7 @@ class YieldTest(CoverageTest): self.assertEqual(self.stdout(), "20\n12\n") def test_yield_from(self): - if env.PYVERSION < (3, 3): + if not env.PYBEHAVIOR.yield_from: self.skipTest("Python before 3.3 doesn't have 'yield from'") self.check_coverage("""\ def gen(inp): @@ -1159,8 +1159,8 @@ class OptimizedIfTest(CoverageTest): arcz=".1 1C CE EF F.", ) - def test_constant_if(self): - if env.PYPY: + def test_if_debug(self): + if not env.PYBEHAVIOR.optimize_if_debug: self.skipTest("PyPy doesn't optimize away 'if __debug__:'") # CPython optimizes away "if __debug__:" self.check_coverage("""\ @@ -1173,13 +1173,17 @@ class OptimizedIfTest(CoverageTest): """, arcz=".1 12 24 41 26 61 1.", ) + + def test_if_not_debug(self): # Before 3.7, no Python optimized away "if not __debug__:" - if env.PYVERSION < (3, 7, 0, 'alpha', 4): - arcz = ".1 12 23 31 34 41 26 61 1." - arcz_missing = "34 41" - else: + if not env.PYBEHAVIOR.optimize_if_debug: + self.skipTest("PyPy doesn't optimize away 'if __debug__:'") + elif env.PYBEHAVIOR.optimize_if_not_debug: arcz = ".1 12 23 31 26 61 1." arcz_missing = "" + else: + arcz = ".1 12 23 31 34 41 26 61 1." + arcz_missing = "34 41" self.check_coverage("""\ for value in [True, False]: if value: @@ -1230,7 +1234,7 @@ class MiscArcTest(CoverageTest): ) def test_unpacked_literals(self): - if env.PYVERSION < (3, 5): + if not env.PYBEHAVIOR.unpackings_pep448: self.skipTest("Don't have unpacked literals until 3.5") self.check_coverage("""\ d = { @@ -1492,7 +1496,7 @@ class AsyncTest(CoverageTest): """Tests of the new async and await keywords in Python 3.5""" def setUp(self): - if env.PYVERSION < (3, 5): + if not env.PYBEHAVIOR.async_syntax: self.skipTest("Async features are new in Python 3.5") super(AsyncTest, self).setUp() diff --git a/tests/test_data.py b/tests/test_data.py index bda73810..3f96288f 100644 --- a/tests/test_data.py +++ b/tests/test_data.py @@ -199,6 +199,22 @@ class CoverageDataTest(DataTestHelpers, CoverageTest): covdata.add_run_info(count=17) self.assertEqual(covdata.run_infos(), [{"hello": "there", "count": 17}]) + def test_no_duplicate_lines(self): + covdata = CoverageData() + covdata.set_context("context1") + covdata.add_lines(LINES_1) + covdata.set_context("context2") + covdata.add_lines(LINES_1) + self.assertEqual(covdata.lines('a.py'), A_PY_LINES_1) + + def test_no_duplicate_arcs(self): + covdata = CoverageData() + covdata.set_context("context1") + covdata.add_arcs(ARCS_3) + covdata.set_context("context2") + covdata.add_arcs(ARCS_3) + self.assertEqual(covdata.arcs('x.py'), X_PY_ARCS_3) + def test_no_arcs_vs_unmeasured_file(self): covdata = CoverageData() covdata.add_arcs(ARCS_3) diff --git a/tests/test_files.py b/tests/test_files.py index b4490ea6..e271da1b 100644 --- a/tests/test_files.py +++ b/tests/test_files.py @@ -57,6 +57,19 @@ class FilesTest(CoverageTest): rel = os.path.join('sub', trick, 'file1.py') self.assertEqual(files.relative_filename(abs_file(rel)), rel) + def test_canonical_filename_ensure_cache_hit(self): + self.make_file("sub/proj1/file1.py") + d = actual_path(self.abs_path("sub/proj1")) + self.chdir(d) + files.set_relative_directory() + canonical_path = files.canonical_filename('sub/proj1/file1.py') + self.assertEqual(canonical_path, self.abs_path('file1.py')) + # After the filename has been converted, it should be in the cache. + self.assertIn('sub/proj1/file1.py', files.CANONICAL_FILENAME_CACHE) + self.assertEqual( + files.canonical_filename('sub/proj1/file1.py'), + self.abs_path('file1.py')) + @pytest.mark.parametrize("original, flat", [ (u"a/b/c.py", u"a_b_c_py"), diff --git a/tests/test_plugins.py b/tests/test_plugins.py index d3365a6d..14d07c1a 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -4,6 +4,7 @@ """Tests for plugins.""" import os.path +from xml.etree import ElementTree import coverage from coverage import env @@ -455,14 +456,25 @@ class GoodFileTracerTest(FileTracerTest): 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) + dom = ElementTree.parse("coverage.xml") + classes = {} + for elt in dom.findall(".//class"): + classes[elt.get('name')] = elt + + assert classes['bar_4.html'].attrib == { + 'branch-rate': '1', + 'complexity': '0', + 'filename': 'bar_4.html', + 'line-rate': '0.5', + 'name': 'bar_4.html', + } + assert classes['foo_7.html'].attrib == { + 'branch-rate': '1', + 'complexity': '0', + 'filename': 'foo_7.html', + 'line-rate': '0.2857', + 'name': 'foo_7.html', + } def test_defer_to_python(self): # A plugin that measures, but then wants built-in python reporting. diff --git a/tests/test_process.py b/tests/test_process.py index a1e71f1c..f234a9ef 100644 --- a/tests/test_process.py +++ b/tests/test_process.py @@ -11,6 +11,7 @@ import os.path import re import sys import textwrap +from xml.etree import ElementTree import pytest @@ -1266,12 +1267,18 @@ class UnicodeFilePathsTest(CoverageTest): self.assertEqual(out, "") with open("coverage.xml", "rb") as xmlf: xml = xmlf.read() - self.assertIn(u' filename="\xe2/accented.py"'.encode('utf8'), xml) - self.assertIn(u' name="accented.py"'.encode('utf8'), xml) - self.assertIn( - u'<package branch-rate="0" complexity="0" line-rate="1" name="\xe2">'.encode('utf8'), - xml - ) + self.assertIn(b' filename="\xc3\xa2/accented.py"', xml) + self.assertIn(b' name="accented.py"', xml) + + dom = ElementTree.parse("coverage.xml") + elts = dom.findall(u".//package[@name='â']") + assert len(elts) == 1 + assert elts[0].attrib == { + "branch-rate": u"0", + "complexity": u"0", + "line-rate": u"1", + "name": u"â", + } report_expected = ( u"Name Stmts Miss Cover\n" diff --git a/tests/test_templite.py b/tests/test_templite.py index 16942db8..3b1e38af 100644 --- a/tests/test_templite.py +++ b/tests/test_templite.py @@ -252,13 +252,23 @@ class TempliteTest(CoverageTest): "@{% for n in nums -%}\n" " {% for a in abc -%}\n" " {# this disappears completely -#}\n" - " {{a -}}\n" + " {{a-}}\n" " {{n -}}\n" + " {{n -}}\n" " {% endfor %}\n" "{% endfor %}!\n", {'nums': [0, 1, 2], 'abc': ['a', 'b', 'c']}, - "@a0b0c0\na1b1c1\na2b2c2\n!\n" + "@a00b00c00\na11b11c11\na22b22c22\n!\n" ) + self.try_render( + "@{% for n in nums -%}\n" + " {{n -}}\n" + " x\n" + "{% endfor %}!\n", + {'nums': [0, 1, 2]}, + "@0x\n1x\n2x\n!\n" + ) + self.try_render(" hello ", {}, " hello ") def test_non_ascii(self): self.try_render( @@ -269,8 +279,8 @@ class TempliteTest(CoverageTest): def test_exception_during_evaluation(self): # TypeError: Couldn't evaluate {{ foo.bar.baz }}: - msg = "Couldn't evaluate None.bar" - with self.assertRaisesRegex(TempliteValueError, msg): + regex = "^Couldn't evaluate None.bar$" + with self.assertRaisesRegex(TempliteValueError, regex): self.try_render( "Hey {{foo.bar.baz}} there", {'foo': None}, "Hey ??? there" ) diff --git a/tests/test_xml.py b/tests/test_xml.py index 185e6ad1..09ab2f85 100644 --- a/tests/test_xml.py +++ b/tests/test_xml.py @@ -7,6 +7,7 @@ import os import os.path import re +from xml.etree import ElementTree import coverage from coverage.backward import import_local_file @@ -14,7 +15,6 @@ from coverage.files import abs_file from tests.coveragetest import CoverageTest from tests.goldtest import change_dir, compare, gold_path -from tests.helpers import re_line, re_lines class XmlTestHelpers(CoverageTest): @@ -30,7 +30,7 @@ class XmlTestHelpers(CoverageTest): self.make_file("sub/__init__.py") self.make_file("sub/doit.py", "print('doit!')") self.make_file("main.py", "import sub.doit") - cov = coverage.Coverage() + cov = coverage.Coverage(source=["."]) self.start_import_stop(cov, "main") return cov @@ -59,10 +59,36 @@ class XmlTestHelpers(CoverageTest): filename = here("f{0}.py".format(i)) self.make_file(filename, "# {0}\n".format(filename)) - def assert_source(self, xml, src): + def assert_source(self, xmldom, src): """Assert that the XML has a <source> element with `src`.""" src = abs_file(src) - self.assertRegex(xml, r'<source>\s*{0}\s*</source>'.format(re.escape(src))) + elts = xmldom.findall(".//sources/source") + assert any(elt.text == src for elt in elts) + + +class XmlTestHelpersTest(XmlTestHelpers, CoverageTest): + """Tests of methods in XmlTestHelpers.""" + + def test_assert_source(self): + dom = ElementTree.fromstring("""\ + <doc> + <src>foo</src> + <sources> + <source>{cwd}something</source> + <source>{cwd}another</source> + </sources> + </doc> + """.format(cwd=abs_file(".")+os.sep)) + + self.assert_source(dom, "something") + self.assert_source(dom, "another") + + with self.assertRaises(AssertionError): + self.assert_source(dom, "hello") + with self.assertRaises(AssertionError): + self.assert_source(dom, "foo") + with self.assertRaises(AssertionError): + self.assert_source(dom, "thing") class XmlReportTest(XmlTestHelpers, CoverageTest): @@ -110,25 +136,28 @@ class XmlReportTest(XmlTestHelpers, CoverageTest): def test_filename_format_showing_everything(self): cov = self.run_doit() - cov.xml_report(outfile="-") - xml = self.stdout() - doit_line = re_line(xml, "class.*doit") - self.assertIn('filename="sub/doit.py"', doit_line) + cov.xml_report() + dom = ElementTree.parse("coverage.xml") + elts = dom.findall(".//class[@name='doit.py']") + assert len(elts) == 1 + assert elts[0].get('filename') == "sub/doit.py" def test_filename_format_including_filename(self): cov = self.run_doit() - cov.xml_report(["sub/doit.py"], outfile="-") - xml = self.stdout() - doit_line = re_line(xml, "class.*doit") - self.assertIn('filename="sub/doit.py"', doit_line) + cov.xml_report(["sub/doit.py"]) + dom = ElementTree.parse("coverage.xml") + elts = dom.findall(".//class[@name='doit.py']") + assert len(elts) == 1 + assert elts[0].get('filename') == "sub/doit.py" def test_filename_format_including_module(self): cov = self.run_doit() import sub.doit # pylint: disable=import-error - cov.xml_report([sub.doit], outfile="-") - xml = self.stdout() - doit_line = re_line(xml, "class.*doit") - self.assertIn('filename="sub/doit.py"', doit_line) + cov.xml_report([sub.doit]) + dom = ElementTree.parse("coverage.xml") + elts = dom.findall(".//class[@name='doit.py']") + assert len(elts) == 1 + assert elts[0].get('filename') == "sub/doit.py" def test_reporting_on_nothing(self): # Used to raise a zero division error: @@ -136,28 +165,31 @@ class XmlReportTest(XmlTestHelpers, CoverageTest): self.make_file("empty.py", "") cov = coverage.Coverage() empty = self.start_import_stop(cov, "empty") - cov.xml_report([empty], outfile="-") - xml = self.stdout() - empty_line = re_line(xml, "class.*empty") - self.assertIn('filename="empty.py"', empty_line) - self.assertIn('line-rate="1"', empty_line) + cov.xml_report([empty]) + dom = ElementTree.parse("coverage.xml") + elts = dom.findall(".//class[@name='empty.py']") + assert len(elts) == 1 + assert elts[0].get('filename') == "empty.py" + assert elts[0].get('line-rate') == '1' def test_empty_file_is_100_not_0(self): # https://bitbucket.org/ned/coveragepy/issue/345 cov = self.run_doit() - cov.xml_report(outfile="-") - xml = self.stdout() - init_line = re_line(xml, 'filename="sub/__init__.py"') - self.assertIn('line-rate="1"', init_line) + cov.xml_report() + dom = ElementTree.parse("coverage.xml") + elts = dom.findall(".//class[@name='__init__.py']") + assert len(elts) == 1 + assert elts[0].get('line-rate') == '1' def test_curdir_source(self): # With no source= option, the XML report should explain that the source # is in the current directory. cov = self.run_doit() - cov.xml_report(outfile="-") - xml = self.stdout() - self.assert_source(xml, ".") - self.assertEqual(xml.count('<source>'), 1) + cov.xml_report() + dom = ElementTree.parse("coverage.xml") + self.assert_source(dom, ".") + sources = dom.findall(".//source") + assert len(sources) == 1 def test_deep_source(self): # When using source=, the XML report needs to mention those directories @@ -170,21 +202,33 @@ class XmlReportTest(XmlTestHelpers, CoverageTest): mod_foo = import_local_file("foo", "src/main/foo.py") # pragma: nested mod_bar = import_local_file("bar", "also/over/there/bar.py") # pragma: nested cov.stop() # pragma: nested - cov.xml_report([mod_foo, mod_bar], outfile="-") - xml = self.stdout() - - self.assert_source(xml, "src/main") - self.assert_source(xml, "also/over/there") - self.assertEqual(xml.count('<source>'), 2) - - self.assertIn( - '<class branch-rate="0" complexity="0" filename="foo.py" line-rate="1" name="foo.py">', - xml - ) - self.assertIn( - '<class branch-rate="0" complexity="0" filename="bar.py" line-rate="1" name="bar.py">', - xml - ) + cov.xml_report([mod_foo, mod_bar]) + dom = ElementTree.parse("coverage.xml") + + self.assert_source(dom, "src/main") + self.assert_source(dom, "also/over/there") + sources = dom.findall(".//source") + assert len(sources) == 2 + + foo_class = dom.findall(".//class[@name='foo.py']") + assert len(foo_class) == 1 + assert foo_class[0].attrib == { + 'branch-rate': '0', + 'complexity': '0', + 'filename': 'foo.py', + 'line-rate': '1', + 'name': 'foo.py', + } + + bar_class = dom.findall(".//class[@name='bar.py']") + assert len(bar_class) == 1 + assert bar_class[0].attrib == { + 'branch-rate': '0', + 'complexity': '0', + 'filename': 'bar.py', + 'line-rate': '1', + 'name': 'bar.py', + } def test_nonascii_directory(self): # https://bitbucket.org/ned/coveragepy/issues/573/cant-generate-xml-report-if-some-source @@ -195,22 +239,33 @@ class XmlReportTest(XmlTestHelpers, CoverageTest): cov.xml_report() +def unbackslash(v): + """Find strings in `v`, and replace backslashes with slashes throughout.""" + if isinstance(v, (tuple, list)): + return [unbackslash(vv) for vv in v] + elif isinstance(v, dict): + return {k: unbackslash(vv) for k, vv in v.items()} + else: + assert isinstance(v, str) + return v.replace("\\", "/") + + class XmlPackageStructureTest(XmlTestHelpers, CoverageTest): """Tests about the package structure reported in the coverage.xml file.""" 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(packages_and_classes, scrubs) + cov.xml_report() + dom = ElementTree.parse("coverage.xml") + for node in dom.iter(): + if node.tag in ('package', 'class'): + yield (node.tag, {a:v for a,v in node.items() if a in ('name', 'filename')}) 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) + self.assertEqual( + unbackslash(list(self.package_and_class_tags(cov))), + unbackslash(result), ) def test_package_names(self): @@ -220,18 +275,18 @@ class XmlPackageStructureTest(XmlTestHelpers, CoverageTest): """) cov = coverage.Coverage(source=".") self.start_import_stop(cov, "main") - 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.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_1(self): self.make_tree(width=1, depth=4) self.make_file("main.py", """\ from d0.d0 import f0 @@ -240,46 +295,62 @@ class XmlPackageStructureTest(XmlTestHelpers, CoverageTest): self.start_import_stop(cov, "main") cov.set_option("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"> + 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"}), + ]) + + def test_package_depth_2(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.set_option("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"> + 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"}), + ]) + + def test_package_depth_3(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.set_option("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"> - """) + 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 test_source_prefix(self): # https://bitbucket.org/ned/coveragepy/issues/465 @@ -287,26 +358,13 @@ class XmlPackageStructureTest(XmlTestHelpers, CoverageTest): self.make_file("src/mod.py", "print(17)") cov = coverage.Coverage(source=["src"]) self.start_import_stop(cov, "mod", modfile="src/mod.py") - self.assert_package_and_class_tags(cov, """\ - <package name="."> - <class filename="mod.py" name="mod.py"> - """) - xml = self.stdout() - self.assert_source(xml, "src") - - -def clean(text, scrub=None): - """Clean text to prepare it for comparison. - - Remove text matching `scrub`, and leading whitespace. Convert backslashes - to forward slashes. - """ - if scrub: - text = re.sub(scrub, "", text) - text = re.sub(r"(?m)^\s+", "", text) - text = re.sub(r"\\", "/", text) - return text + self.assert_package_and_class_tags(cov, [ + ('package', {'name': "."}), + ('class', {'filename': "mod.py", 'name': "mod.py"}), + ]) + dom = ElementTree.parse("coverage.xml") + self.assert_source(dom, "src") def compare_xml(expected, actual, **kwargs): |
