Coverage for tests / test_xml.py: 100.000%
309 statements
« prev ^ index » next coverage.py v7.12.1a0.dev1, created at 2025-11-30 17:57 +0000
« prev ^ index » next coverage.py v7.12.1a0.dev1, created at 2025-11-30 17:57 +0000
1# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
2# For details: https://github.com/coveragepy/coveragepy/blob/main/NOTICE.txt
4"""Tests for XML reports from coverage.py."""
6from __future__ import annotations 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
8import os 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
9import os.path 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
10import re 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
12from typing import Any 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
13from collections.abc import Iterable 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
14from xml.etree import ElementTree 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
16import pytest 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
18import coverage 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
19from coverage import Coverage, env 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
20from coverage.exceptions import NoDataError 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
21from coverage.files import abs_file 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
22from coverage.misc import import_local_file 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
24from tests.coveragetest import CoverageTest 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
25from tests.goldtest import compare, gold_path 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
26from tests.helpers import assert_coverage_warnings, change_dir 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
29class XmlTestHelpers(CoverageTest): 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
30 """Methods to use from XML tests."""
32 def run_doit(self) -> Coverage: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
33 """Construct a simple sub-package."""
34 self.make_file("sub/__init__.py") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
35 self.make_file("sub/doit.py", "print('doit!')") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
36 self.make_file("main.py", "import sub.doit") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
37 cov = coverage.Coverage(source=["."]) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
38 self.start_import_stop(cov, "main") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
39 return cov 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
41 def make_tree(self, width: int, depth: int, curdir: str = ".") -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
42 """Make a tree of packages.
44 Makes `width` directories, named d0 .. d{width-1}. Each directory has
45 __init__.py, and `width` files, named f0.py .. f{width-1}.py. Each
46 directory also has `width` sub-directories, in the same fashion, until
47 a depth of `depth` is reached.
49 """
50 if depth == 0: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
51 return 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
53 def here(p: str) -> str: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
54 """A path for `p` in our currently interesting directory."""
55 return os.path.join(curdir, p) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
57 for i in range(width): 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
58 next_dir = here(f"d{i}") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
59 self.make_tree(width, depth - 1, next_dir) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
60 if curdir != ".": 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
61 self.make_file(here("__init__.py"), "") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
62 for i in range(width): 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
63 filename = here(f"f{i}.py") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
64 self.make_file(filename, f"# {filename}\n") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
66 def assert_source( 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
67 self,
68 xmldom: ElementTree.Element | ElementTree.ElementTree,
69 src: str,
70 ) -> None:
71 """Assert that the XML has a <source> element with `src`."""
72 src = abs_file(src) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
73 elts = xmldom.findall(".//sources/source") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
74 assert any(elt.text == src for elt in elts) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
77class XmlTestHelpersTest(XmlTestHelpers, CoverageTest): 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
78 """Tests of methods in XmlTestHelpers."""
80 run_in_temp_dir = False 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
82 def test_assert_source(self) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
83 dom = ElementTree.fromstring( 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
84 """\
85 <doc>
86 <src>foo</src>
87 <sources>
88 <source>{cwd}something</source>
89 <source>{cwd}another</source>
90 </sources>
91 </doc>
92 """.format(cwd=abs_file(".") + os.sep)
93 )
95 self.assert_source(dom, "something") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
96 self.assert_source(dom, "another") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
98 with pytest.raises(AssertionError): 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
99 self.assert_source(dom, "hello") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
100 with pytest.raises(AssertionError): 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
101 self.assert_source(dom, "foo") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
102 with pytest.raises(AssertionError): 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
103 self.assert_source(dom, "thing") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
106class XmlReportTest(XmlTestHelpers, CoverageTest): 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
107 """Tests of the XML reports from coverage.py."""
109 def make_mycode_data(self) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
110 """Pretend that we ran mycode.py, so we can report on it."""
111 self.make_file("mycode.py", "print('hello')\n") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
112 self.make_data_file(lines={abs_file("mycode.py"): [1]}) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
114 def run_xml_report(self, **kwargs: Any) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
115 """Run xml_report()"""
116 cov = coverage.Coverage() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
117 cov.load() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
118 cov.xml_report(**kwargs) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
120 def test_default_file_placement(self) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
121 self.make_mycode_data() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
122 self.run_xml_report() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
123 self.assert_exists("coverage.xml") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
124 assert self.stdout() == "" 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
126 def test_argument_affects_xml_placement(self) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
127 self.make_mycode_data() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
128 cov = coverage.Coverage(messages=True) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
129 cov.load() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
130 cov.xml_report(outfile="put_it_there.xml") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
131 assert self.stdout() == "Wrote XML report to put_it_there.xml\n" 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
132 self.assert_doesnt_exist("coverage.xml") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
133 self.assert_exists("put_it_there.xml") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
135 def test_output_directory_does_not_exist(self) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
136 self.make_mycode_data() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
137 self.run_xml_report(outfile="nonexistent/put_it_there.xml") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
138 self.assert_doesnt_exist("coverage.xml") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
139 self.assert_doesnt_exist("put_it_there.xml") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
140 self.assert_exists("nonexistent/put_it_there.xml") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
142 def test_config_affects_xml_placement(self) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
143 self.make_mycode_data() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
144 self.make_file(".coveragerc", "[xml]\noutput = xml.out\n") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
145 self.run_xml_report() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
146 self.assert_doesnt_exist("coverage.xml") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
147 self.assert_exists("xml.out") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
149 def test_no_data(self) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
150 # https://github.com/coveragepy/coveragepy/issues/210
151 with pytest.raises(NoDataError, match="No data to report."): 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
152 self.run_xml_report() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
153 self.assert_doesnt_exist("coverage.xml") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
154 self.assert_doesnt_exist(".coverage") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
156 def test_no_source(self) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
157 # Written while investigating a bug, might as well keep it.
158 # https://github.com/coveragepy/coveragepy/issues/208
159 self.make_file("innocuous.py", "a = 4") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
160 cov = coverage.Coverage() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
161 self.start_import_stop(cov, "innocuous") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
162 os.remove("innocuous.py") 1EaFbuGcHdWvIeJf2wKgLhXxMiNjyOkPlYzQmRn4ASoTpZBUqVr0CstD
163 with pytest.warns(Warning) as warns: 1EaFbuGcHdWvIeJf2wKgLhXxMiNjyOkPlYzQmRn4ASoTpZBUqVr0CstD
164 cov.xml_report(ignore_errors=True) 1EaFbuGcHdWvIeJf2wKgLhXxMiNjyOkPlYzQmRn4ASoTpZBUqVr0CstD
165 assert_coverage_warnings( 1EaFbuGcHdWvIeJf2wKgLhXxMiNjyOkPlYzQmRn4ASoTpZBUqVr0CstD
166 warns,
167 re.compile(r"Couldn't parse '.*innocuous.py'. \(couldnt-parse\)"),
168 )
169 self.assert_exists("coverage.xml") 1EaFbuGcHdWvIeJf2wKgLhXxMiNjyOkPlYzQmRn4ASoTpZBUqVr0CstD
171 def test_filename_format_showing_everything(self) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
172 cov = self.run_doit() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
173 cov.xml_report() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRnASoTpZBUqVr0CstD
174 dom = ElementTree.parse("coverage.xml") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRnASoTpZBUqVr0CstD
175 elts = dom.findall(".//class[@name='doit.py']") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRnASoTpZBUqVr0CstD
176 assert len(elts) == 1 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRnASoTpZBUqVr0CstD
177 assert elts[0].get("filename") == "sub/doit.py" 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRnASoTpZBUqVr0CstD
179 def test_filename_format_including_filename(self) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
180 cov = self.run_doit() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
181 cov.xml_report(["sub/doit.py"]) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
182 dom = ElementTree.parse("coverage.xml") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
183 elts = dom.findall(".//class[@name='doit.py']") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
184 assert len(elts) == 1 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
185 assert elts[0].get("filename") == "sub/doit.py" 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
187 def test_filename_format_including_module(self) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
188 cov = self.run_doit() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
189 import sub.doit # pylint: disable=import-error 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
191 cov.xml_report([sub.doit]) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
192 dom = ElementTree.parse("coverage.xml") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
193 elts = dom.findall(".//class[@name='doit.py']") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
194 assert len(elts) == 1 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
195 assert elts[0].get("filename") == "sub/doit.py" 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
197 def test_reporting_on_nothing(self) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
198 # Used to raise a zero division error:
199 # https://github.com/coveragepy/coveragepy/issues/250
200 self.make_file("empty.py", "") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
201 cov = coverage.Coverage() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
202 empty = self.start_import_stop(cov, "empty") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
203 cov.xml_report([empty]) 1EaFb1uGcHdWvIeJfwKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
204 dom = ElementTree.parse("coverage.xml") 1EaFb1uGcHdWvIeJfwKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
205 elts = dom.findall(".//class[@name='empty.py']") 1EaFb1uGcHdWvIeJfwKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
206 assert len(elts) == 1 1EaFb1uGcHdWvIeJfwKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
207 assert elts[0].get("filename") == "empty.py" 1EaFb1uGcHdWvIeJfwKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
208 assert elts[0].get("line-rate") == "1" 1EaFb1uGcHdWvIeJfwKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
210 def test_empty_file_is_100_not_0(self) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
211 # https://github.com/coveragepy/coveragepy/issues/345
212 cov = self.run_doit() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
213 cov.xml_report() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
214 dom = ElementTree.parse("coverage.xml") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
215 elts = dom.findall(".//class[@name='__init__.py']") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
216 assert len(elts) == 1 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
217 assert elts[0].get("line-rate") == "1" 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
219 def test_empty_file_is_skipped(self) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
220 cov = self.run_doit() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
221 cov.xml_report(skip_empty=True) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
222 dom = ElementTree.parse("coverage.xml") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
223 elts = dom.findall(".//class[@name='__init__.py']") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
224 assert len(elts) == 0 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
226 def test_curdir_source(self) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
227 # With no source= option, the XML report should explain that the source
228 # is in the current directory.
229 cov = self.run_doit() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
230 cov.xml_report() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
231 dom = ElementTree.parse("coverage.xml") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
232 self.assert_source(dom, ".") # type: ignore[arg-type] 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
233 sources = dom.findall(".//source") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
234 assert len(sources) == 1 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
236 def test_deep_source(self) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
237 # When using source=, the XML report needs to mention those directories
238 # in the <source> elements.
239 # https://github.com/coveragepy/coveragepy/issues/439
240 self.make_file("src/main/foo.py", "a = 1") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
241 self.make_file("also/over/there/bar.py", "b = 2") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
243 cov = coverage.Coverage(source=["src/main", "also/over/there", "not/really"]) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
244 with cov.collect(): 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
245 mod_foo = import_local_file("foo", "src/main/foo.py") 1abucdvefwghxijyklzmnAopBqrCstD
246 mod_bar = import_local_file("bar", "also/over/there/bar.py") 1abucdvefwghxijyklzmnAopBqrCstD
248 with pytest.warns(Warning) as warns: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRnASoTpZBUqVr0CstD
249 cov.xml_report([mod_foo, mod_bar]) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRnASoTpZBUqVr0CstD
250 assert_coverage_warnings( 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRnASoTpZBUqVr0CstD
251 warns,
252 "Module not/really was never imported. (module-not-imported)",
253 )
254 dom = ElementTree.parse("coverage.xml") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRnASoTpZBUqVr0CstD
256 self.assert_source(dom, "src/main") # type: ignore[arg-type] 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRnASoTpZBUqVr0CstD
257 self.assert_source(dom, "also/over/there") # type: ignore[arg-type] 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRnASoTpZBUqVr0CstD
258 sources = dom.findall(".//source") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRnASoTpZBUqVr0CstD
259 assert len(sources) == 2 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRnASoTpZBUqVr0CstD
261 foo_class = dom.findall(".//class[@name='foo.py']") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRnASoTpZBUqVr0CstD
262 assert len(foo_class) == 1 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRnASoTpZBUqVr0CstD
263 assert foo_class[0].attrib == { 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRnASoTpZBUqVr0CstD
264 "branch-rate": "0",
265 "complexity": "0",
266 "filename": "foo.py",
267 "line-rate": "1",
268 "name": "foo.py",
269 }
271 bar_class = dom.findall(".//class[@name='bar.py']") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRnASoTpZBUqVr0CstD
272 assert len(bar_class) == 1 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRnASoTpZBUqVr0CstD
273 assert bar_class[0].attrib == { 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRnASoTpZBUqVr0CstD
274 "branch-rate": "0",
275 "complexity": "0",
276 "filename": "bar.py",
277 "line-rate": "1",
278 "name": "bar.py",
279 }
281 def test_nonascii_directory(self) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
282 # https://github.com/coveragepy/coveragepy/issues/573
283 self.make_file("테스트/program.py", "a = 1") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
284 with change_dir("테스트"): 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
285 cov = coverage.Coverage() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
286 self.start_import_stop(cov, "program") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
287 cov.xml_report() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNjyOkPlYzQmRn4ASoTpZBUqVr0CstD
289 def test_accented_dot_py(self) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
290 # Make a file with a non-ascii character in the filename.
291 self.make_file("h\xe2t.py", "print('accented')") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
292 self.make_data_file(lines={abs_file("h\xe2t.py"): [1]}) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
293 cov = coverage.Coverage() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
294 cov.load() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
295 cov.xml_report() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
296 # The XML report is always UTF8-encoded.
297 with open("coverage.xml", "rb") as xmlf: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
298 xml = xmlf.read() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
299 assert ' filename="h\xe2t.py"'.encode() in xml 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
300 assert ' name="h\xe2t.py"'.encode() in xml 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
302 def test_accented_directory(self) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
303 # Make a file with a non-ascii character in the directory name.
304 self.make_file("\xe2/accented.py", "print('accented')") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
305 self.make_data_file(lines={abs_file("\xe2/accented.py"): [1]}) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
307 # The XML report is always UTF8-encoded.
308 cov = coverage.Coverage() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
309 cov.load() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
310 cov.xml_report() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
311 with open("coverage.xml", "rb") as xmlf: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
312 xml = xmlf.read() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
313 assert b' filename="\xc3\xa2/accented.py"' in xml 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
314 assert b' name="accented.py"' in xml 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
316 dom = ElementTree.parse("coverage.xml") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
317 elts = dom.findall(".//package[@name='â']") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
318 assert len(elts) == 1 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
319 assert elts[0].attrib == { 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
320 "branch-rate": "0",
321 "complexity": "0",
322 "line-rate": "1",
323 "name": "â",
324 }
326 def test_no_duplicate_packages(self) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
327 self.make_file( 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
328 "namespace/package/__init__.py",
329 "from . import sample; from . import test; from .subpackage import test",
330 )
331 self.make_file("namespace/package/sample.py", "print('package.sample')") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
332 self.make_file("namespace/package/test.py", "print('package.test')") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
333 self.make_file("namespace/package/subpackage/test.py", "print('package.subpackage.test')") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
335 # no source path passed to coverage!
336 # problem occurs when they are dynamically generated during xml report
337 cov = coverage.Coverage() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
338 with cov.collect(): 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
339 import_local_file("namespace.package", "namespace/package/__init__.py") 1abucdvefwghxijyklzmnAopBqrCstD
341 cov.xml_report() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
343 dom = ElementTree.parse("coverage.xml") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
345 # only two packages should be present
346 packages = dom.findall(".//package") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
347 assert len(packages) == 2 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
349 # one of them is namespace.package
350 named_package = dom.findall(".//package[@name='namespace.package']") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
351 assert len(named_package) == 1 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
353 # the other one namespace.package.subpackage
354 named_sub_package = dom.findall(".//package[@name='namespace.package.subpackage']") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
355 assert len(named_sub_package) == 1 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
357 def test_bug_1709(self) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
358 # https://github.com/coveragepy/coveragepy/issues/1709
359 self.make_file("main.py", "import x1y, x01y, x001y") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
360 self.make_file("x1y.py", "print('x1y')") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
361 self.make_file("x01y.py", "print('x01y')") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
362 self.make_file("x001y.py", "print('x001y')") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
364 cov = coverage.Coverage() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
365 self.start_import_stop(cov, "main") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
366 assert self.stdout() == "x1y\nx01y\nx001y\n" 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
367 # This used to raise:
368 # TypeError: '<' not supported between instances of 'Element' and 'Element'
369 cov.xml_report() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
372def unbackslash(v: Any) -> Any: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
373 """Find strings in `v`, and replace backslashes with slashes throughout."""
374 if isinstance(v, (tuple, list)): 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
375 return [unbackslash(vv) for vv in v] 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
376 elif isinstance(v, dict): 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
377 return {k: unbackslash(vv) for k, vv in v.items()} 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
378 else:
379 assert isinstance(v, str) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
380 return v.replace("\\", "/") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
383class XmlPackageStructureTest(XmlTestHelpers, CoverageTest): 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
384 """Tests about the package structure reported in the coverage.xml file."""
386 def package_and_class_tags(self, cov: Coverage) -> Iterable[tuple[str, dict[str, Any]]]: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
387 """Run an XML report on `cov`, and get the package and class tags."""
388 cov.xml_report() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
389 dom = ElementTree.parse("coverage.xml") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
390 for node in dom.iter(): 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
391 if node.tag in ["package", "class"]: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
392 yield (node.tag, {a: v for a, v in node.items() if a in ["name", "filename"]}) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
394 def assert_package_and_class_tags(self, cov: Coverage, result: Any) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
395 """Check the XML package and class tags from `cov` match `result`."""
396 assert unbackslash(list(self.package_and_class_tags(cov))) == unbackslash(result) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
398 def test_package_names(self) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
399 self.make_tree(width=1, depth=3) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
400 self.make_file( 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
401 "main.py",
402 """\
403 from d0.d0 import f0
404 """,
405 )
406 cov = coverage.Coverage(source=["."]) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
407 self.start_import_stop(cov, "main") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
408 self.assert_package_and_class_tags( 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
409 cov,
410 [
411 ("package", {"name": "."}),
412 ("class", {"filename": "main.py", "name": "main.py"}),
413 ("package", {"name": "d0"}),
414 ("class", {"filename": "d0/__init__.py", "name": "__init__.py"}),
415 ("class", {"filename": "d0/f0.py", "name": "f0.py"}),
416 ("package", {"name": "d0.d0"}),
417 ("class", {"filename": "d0/d0/__init__.py", "name": "__init__.py"}),
418 ("class", {"filename": "d0/d0/f0.py", "name": "f0.py"}),
419 ],
420 )
422 def test_package_depth_1(self) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
423 self.make_tree(width=1, depth=4) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
424 self.make_file( 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
425 "main.py",
426 """\
427 from d0.d0 import f0
428 """,
429 )
430 cov = coverage.Coverage(source=["."]) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
431 self.start_import_stop(cov, "main") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
433 cov.set_option("xml:package_depth", 1) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
434 self.assert_package_and_class_tags( 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
435 cov,
436 [
437 ("package", {"name": "."}),
438 ("class", {"filename": "main.py", "name": "main.py"}),
439 ("package", {"name": "d0"}),
440 ("class", {"filename": "d0/__init__.py", "name": "__init__.py"}),
441 ("class", {"filename": "d0/d0/__init__.py", "name": "d0/__init__.py"}),
442 ("class", {"filename": "d0/d0/d0/__init__.py", "name": "d0/d0/__init__.py"}),
443 ("class", {"filename": "d0/d0/d0/f0.py", "name": "d0/d0/f0.py"}),
444 ("class", {"filename": "d0/d0/f0.py", "name": "d0/f0.py"}),
445 ("class", {"filename": "d0/f0.py", "name": "f0.py"}),
446 ],
447 )
449 def test_package_depth_2(self) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
450 self.make_tree(width=1, depth=4) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
451 self.make_file( 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
452 "main.py",
453 """\
454 from d0.d0 import f0
455 """,
456 )
457 cov = coverage.Coverage(source=["."]) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
458 self.start_import_stop(cov, "main") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
460 cov.set_option("xml:package_depth", 2) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
461 self.assert_package_and_class_tags( 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
462 cov,
463 [
464 ("package", {"name": "."}),
465 ("class", {"filename": "main.py", "name": "main.py"}),
466 ("package", {"name": "d0"}),
467 ("class", {"filename": "d0/__init__.py", "name": "__init__.py"}),
468 ("class", {"filename": "d0/f0.py", "name": "f0.py"}),
469 ("package", {"name": "d0.d0"}),
470 ("class", {"filename": "d0/d0/__init__.py", "name": "__init__.py"}),
471 ("class", {"filename": "d0/d0/d0/__init__.py", "name": "d0/__init__.py"}),
472 ("class", {"filename": "d0/d0/d0/f0.py", "name": "d0/f0.py"}),
473 ("class", {"filename": "d0/d0/f0.py", "name": "f0.py"}),
474 ],
475 )
477 def test_package_depth_3(self) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
478 self.make_tree(width=1, depth=4) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
479 self.make_file( 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
480 "main.py",
481 """\
482 from d0.d0 import f0
483 """,
484 )
485 cov = coverage.Coverage(source=["."]) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
486 self.start_import_stop(cov, "main") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
488 cov.set_option("xml:package_depth", 3) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
489 self.assert_package_and_class_tags( 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
490 cov,
491 [
492 ("package", {"name": "."}),
493 ("class", {"filename": "main.py", "name": "main.py"}),
494 ("package", {"name": "d0"}),
495 ("class", {"filename": "d0/__init__.py", "name": "__init__.py"}),
496 ("class", {"filename": "d0/f0.py", "name": "f0.py"}),
497 ("package", {"name": "d0.d0"}),
498 ("class", {"filename": "d0/d0/__init__.py", "name": "__init__.py"}),
499 ("class", {"filename": "d0/d0/f0.py", "name": "f0.py"}),
500 ("package", {"name": "d0.d0.d0"}),
501 ("class", {"filename": "d0/d0/d0/__init__.py", "name": "__init__.py"}),
502 ("class", {"filename": "d0/d0/d0/f0.py", "name": "f0.py"}),
503 ],
504 )
506 def test_source_prefix(self) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
507 # https://github.com/coveragepy/coveragepy/issues/465
508 # https://github.com/coveragepy/coveragepy/issues/526
509 self.make_file("src/mod.py", "print(17)") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
510 cov = coverage.Coverage(source=["src"]) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
511 self.start_import_stop(cov, "mod", modfile="src/mod.py") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
513 self.assert_package_and_class_tags( 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
514 cov,
515 [
516 ("package", {"name": "."}),
517 ("class", {"filename": "mod.py", "name": "mod.py"}),
518 ],
519 )
520 dom = ElementTree.parse("coverage.xml") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
521 self.assert_source(dom, "src") # type: ignore[arg-type] 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
523 @pytest.mark.parametrize("trail", ["", "/", "\\"]) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
524 def test_relative_source(self, trail: str) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
525 if trail == "\\" and not env.WINDOWS: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
526 pytest.skip("trailing backslash is only for Windows") 1EaFbGcHdIeJfKgLhMiNjOkPlQmRn5SoTp6UqVrst
527 self.make_file("src/mod.py", "print(17)") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
528 cov = coverage.Coverage(source=[f"src{trail}"]) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
529 cov.set_option("run:relative_files", True) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
530 self.start_import_stop(cov, "mod", modfile="src/mod.py") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
531 cov.xml_report() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
533 dom = ElementTree.parse("coverage.xml") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
534 elts = dom.findall(".//sources/source") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
535 assert [elt.text for elt in elts] == ["src"] 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
538def compare_xml(expected: str, actual: str, actual_extra: bool = False) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
539 """Specialized compare function for our XML files."""
540 source_path = coverage.files.relative_directory().rstrip(r"\/") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
542 scrubs = [ 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
543 (r' timestamp="\d+"', ' timestamp="TIMESTAMP"'),
544 (r' version="[-.\w]+"', ' version="VERSION"'),
545 (r"<source>\s*.*?\s*</source>", "<source>%s</source>" % re.escape(source_path)),
546 (r"/coverage\.readthedocs\.io/?[-.\w/]*", "/coverage.readthedocs.io/VER"),
547 ]
548 compare(expected, actual, scrubs=scrubs, actual_extra=actual_extra) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
551class XmlGoldTest(CoverageTest): 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
552 """Tests of XML reporting that use gold files."""
554 def test_a_xml_1(self) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
555 self.make_file( 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
556 "a.py",
557 """\
558 if 1 < 2:
559 # Needed a < to look at HTML entities.
560 a = 3
561 else:
562 a = 4
563 """,
564 )
566 cov = coverage.Coverage() 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
567 a = self.start_import_stop(cov, "a") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
568 cov.xml_report(a, outfile="coverage.xml") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
569 compare_xml(gold_path("xml/x_xml"), ".", actual_extra=True) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
571 def test_a_xml_2(self) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
572 self.make_file( 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
573 "a.py",
574 """\
575 if 1 < 2:
576 # Needed a < to look at HTML entities.
577 a = 3
578 else:
579 a = 4
580 """,
581 )
583 self.make_file( 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
584 "run_a_xml_2.ini",
585 """\
586 # Put all the XML output in xml_2
587 [xml]
588 output = xml_2/coverage.xml
589 """,
590 )
592 cov = coverage.Coverage(config_file="run_a_xml_2.ini") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
593 a = self.start_import_stop(cov, "a") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
594 cov.xml_report(a) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
595 compare_xml(gold_path("xml/x_xml"), "xml_2") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
597 def test_y_xml_branch(self) -> None: 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
598 self.make_file( 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
599 "y.py",
600 """\
601 def choice(x):
602 if x < 2:
603 return 3
604 else:
605 return 4
607 assert choice(1) == 3
608 """,
609 )
611 cov = coverage.Coverage(branch=True) 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
612 y = self.start_import_stop(cov, "y") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOk7Pl8Yz9Qm!Rn54A#So$Tp6ZB%Uq'Vr(0C)stD
613 cov.xml_report(y, outfile="y_xml_branch/coverage.xml") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD
614 compare_xml(gold_path("xml/y_xml_branch"), "y_xml_branch") 1EaFb1uGcHdWvIeJf2wKgLhXxMiNj3yOkPlYzQmRn4ASoTpZBUqVr0CstD