def test_empty_violations(self): """ Test that an empty violations report is handled properly """ # Construct the XML report file_paths = ['file1.py'] violations1 = self.MANY_VIOLATIONS violations2 = set() measured1 = self.FEW_MEASURED measured2 = self.MANY_MEASURED xml = self._coverage_xml(file_paths, violations1, measured1) xml2 = self._coverage_xml(file_paths, violations2, measured2) # Parse the report coverage = XmlCoverageReporter([xml2, xml]) # By construction, each file has the same set # of covered/uncovered lines self.assertEqual( violations1 & violations2, coverage.violations('file1.py') ) self.assertEqual( measured1 | measured2, coverage.measured_lines('file1.py') )
def test_non_python_violations(self): """ Non python projects often just have a file name specified while the full path can be acquired from a sources tag in the XML. This test checks that flow by requesting violation info from a path that can only be constructed by using the path provided in the sources tag """ fancy_path = 'superFancyPath' file_paths = ['file1.java'] source_paths = [fancy_path] violations = self.MANY_VIOLATIONS measured = self.FEW_MEASURED xml = self._coverage_xml(file_paths, violations, measured, source_paths=source_paths) coverage = XmlCoverageReporter([xml]) self.assertEqual( violations, coverage.violations('{0}/{1}'.format(fancy_path, file_paths[0]))) self.assertEqual( measured, coverage.measured_lines('{0}/{1}'.format(fancy_path, file_paths[0])))
def test_three_inputs(self): # Construct the XML report file_paths = ['file1.py'] violations1 = self.MANY_VIOLATIONS violations2 = self.FEW_VIOLATIONS violations3 = self.ONE_VIOLATION measured1 = self.FEW_MEASURED measured2 = self.MANY_MEASURED measured3 = self.VERY_MANY_MEASURED xml = self._coverage_xml(file_paths, violations1, measured1) xml2 = self._coverage_xml(file_paths, violations2, measured2) xml3 = self._coverage_xml(file_paths, violations3, measured3) # Parse the report coverage = XmlCoverageReporter([xml2, xml, xml3]) # By construction, each file has the same set # of covered/uncovered lines self.assertEqual( violations1 & violations2 & violations3, coverage.violations('file1.py') ) self.assertEqual( measured1 | measured2 | measured3, coverage.measured_lines('file1.py') )
def test_empty_violations(self): """ Test that an empty violations report is handled properly """ # Construct the XML report file_paths = ['file1.py'] violations1 = self.MANY_VIOLATIONS violations2 = set() measured1 = self.FEW_MEASURED measured2 = self.MANY_MEASURED xml = self._coverage_xml(file_paths, violations1, measured1) xml2 = self._coverage_xml(file_paths, violations2, measured2) # Parse the report coverage = XmlCoverageReporter([xml2, xml]) # By construction, each file has the same set # of covered/uncovered lines self.assertEqual(violations1 & violations2, coverage.violations('file1.py')) self.assertEqual(measured1 | measured2, coverage.measured_lines('file1.py'))
def test_three_inputs(self): # Construct the XML report file_paths = ['file1.py'] violations1 = self.MANY_VIOLATIONS violations2 = self.FEW_VIOLATIONS violations3 = self.ONE_VIOLATION measured1 = self.FEW_MEASURED measured2 = self.MANY_MEASURED measured3 = self.VERY_MANY_MEASURED xml = self._coverage_xml(file_paths, violations1, measured1) xml2 = self._coverage_xml(file_paths, violations2, measured2) xml3 = self._coverage_xml(file_paths, violations3, measured3) # Parse the report coverage = XmlCoverageReporter([xml2, xml, xml3]) # By construction, each file has the same set # of covered/uncovered lines self.assertEqual(violations1 & violations2 & violations3, coverage.violations('file1.py')) self.assertEqual(measured1 | measured2 | measured3, coverage.measured_lines('file1.py'))
def test_no_such_file(self): # Construct the XML report with no source files xml = self._coverage_xml([], [], []) # Parse the report coverage = XmlCoverageReporter(xml) # Expect that we get no results result = coverage.violations('file.py') self.assertEqual(result, set([]))
def test_different_files_in_inputs(self): # Construct the XML report xml_roots = [ self._coverage_xml(['file.py'], self.MANY_VIOLATIONS, self.FEW_MEASURED), self._coverage_xml(['other_file.py'], self.FEW_VIOLATIONS, self.MANY_MEASURED) ] # Parse the report coverage = XmlCoverageReporter(xml_roots) self.assertEqual(self.MANY_VIOLATIONS, coverage.violations('file.py')) self.assertEqual(self.FEW_VIOLATIONS, coverage.violations('other_file.py'))
def test_get_src_path_clover(): GitPathTool._cwd = "/" GitPathTool._root = "/" clover_report = etree.parse( StringIO("""<?xml version="1.0" encoding="UTF-8"?> <coverage generated="1622182664251" clover="3.2.0"> <project timestamp="1622182664251" name="All files"> <metrics statements="8" coveredstatements="8" conditionals="6" coveredconditionals="5" methods="2" coveredmethods="2" elements="16" coveredelements="15" complexity="0" loc="8" ncloc="8" packages="2" files="2" classes="2"/> <package name="src"> <metrics statements="6" coveredstatements="6" conditionals="4" coveredconditionals="4" methods="1" coveredmethods="1"/> <file name="isLucky.js" path="isLucky.js"> <metrics statements="6" coveredstatements="6" conditionals="4" coveredconditionals="4" methods="1" coveredmethods="1"/> <line num="2" count="3" type="cond" truecount="2" falsecount="0"/> <line num="3" count="1" type="stmt"/> <line num="5" count="2" type="cond" truecount="2" falsecount="0"/> <line num="6" count="1" type="stmt"/> <line num="8" count="1" type="stmt"/> <line num="12" count="1" type="stmt"/> </file> </package> <package name="src.test"> <metrics statements="2" coveredstatements="2" conditionals="2" coveredconditionals="1" methods="1" coveredmethods="1"/> <file name="isLucky2.js" path="isLucky2.js"> <metrics statements="2" coveredstatements="2" conditionals="2" coveredconditionals="1" methods="1" coveredmethods="1"/> <line num="1" count="1" type="cond" truecount="1" falsecount="1"/> <line num="3" count="1" type="stmt"/> </file> </package> </project> </coverage>""")) result = XmlCoverageReporter.get_src_path_line_nodes_clover( clover_report, "isLucky.js") assert sorted([int(line.attrib["num"]) for line in result]) == [2, 3, 5, 6, 8, 12]
def generate_coverage_report(coverage_xml, compare_branch, html_report=None, css_file=None, ignore_staged=False, ignore_unstaged=False, exclude=None, src_roots=None): """ Generate the diff coverage report, using kwargs from `parse_args()`. """ diff = GitDiffReporter( compare_branch, git_diff=GitDiffTool(), ignore_staged=ignore_staged, ignore_unstaged=ignore_unstaged, exclude=exclude) xml_roots = [cElementTree.parse(xml_root) for xml_root in coverage_xml] coverage = XmlCoverageReporter(xml_roots, src_roots) # Build a report generator if html_report is not None: css_url = css_file if css_url is not None: css_url = os.path.relpath(css_file, os.path.dirname(html_report)) reporter = HtmlReportGenerator(coverage, diff, css_url=css_url) with open(html_report, "wb") as output_file: reporter.generate_report(output_file) if css_file is not None: with open(css_file, "wb") as output_file: reporter.generate_css(output_file) reporter = StringReportGenerator(coverage, diff) output_file = sys.stdout if six.PY2 else sys.stdout.buffer # Generate the report reporter.generate_report(output_file) return reporter.total_percent_covered()
def coverage_xml_parse(xml_file_path, src_file_path): from diff_cover.violationsreporters.violations_reporter import XmlCoverageReporter from diff_cover.git_path import GitPathTool try: # Needed for Python < 3.3, works up to 3.8 import xml.etree.cElementTree as etree except ImportError: # Python 3.9 onwards import xml.etree.ElementTree as etree GitPathTool.set_cwd(None) xml_roots = [etree.parse(xml_root) for xml_root in [xml_file_path]] coverage = XmlCoverageReporter(xml_roots, [os.path.dirname(src_file_path)]) coverage._cache_file(src_file_path) return coverage._info_cache[src_file_path]
def generate_coverage_report(coverage_xml, compare_branch, html_report=None, ignore_unstaged=False): """ Generate the diff coverage report, using kwargs from `parse_args()`. """ diff = GitDiffReporter(compare_branch, git_diff=GitDiffTool(), ignore_unstaged=ignore_unstaged) xml_roots = [cElementTree.parse(xml_root) for xml_root in coverage_xml] coverage = XmlCoverageReporter(xml_roots) # Build a report generator if html_report is not None: reporter = HtmlReportGenerator(coverage, diff) with open(html_report, "wb") as output_file: reporter.generate_report(output_file) reporter = StringReportGenerator(coverage, diff) output_file = sys.stdout if six.PY2 else sys.stdout.buffer # Generate the report reporter.generate_report(output_file) return reporter.total_percent_covered()
def generate_coverage_report( coverage_xml, compare_branch, html_report=None, css_file=None, json_report=None, markdown_report=None, ignore_staged=False, ignore_unstaged=False, exclude=None, src_roots=None, diff_range_notation=None, ignore_whitespace=False, quiet=False, show_uncovered=False, ): """ Generate the diff coverage report, using kwargs from `parse_args()`. """ diff = GitDiffReporter( compare_branch, git_diff=GitDiffTool(diff_range_notation, ignore_whitespace), ignore_staged=ignore_staged, ignore_unstaged=ignore_unstaged, exclude=exclude, ) xml_roots = [etree.parse(xml_root) for xml_root in coverage_xml] coverage = XmlCoverageReporter(xml_roots, src_roots) # Build a report generator if html_report is not None: css_url = css_file if css_url is not None: css_url = os.path.relpath(css_file, os.path.dirname(html_report)) reporter = HtmlReportGenerator(coverage, diff, css_url=css_url) with open(html_report, "wb") as output_file: reporter.generate_report(output_file) if css_file is not None: with open(css_file, "wb") as output_file: reporter.generate_css(output_file) elif json_report is not None: reporter = JsonReportGenerator(coverage, diff) with open(json_report, "wb") as output_file: reporter.generate_report(output_file) elif markdown_report is not None: reporter = MarkdownReportGenerator(coverage, diff) with open(markdown_report, "wb") as output_file: reporter.generate_report(output_file) # Generate the report for stdout reporter = StringReportGenerator(coverage, diff, show_uncovered) output_file = io.BytesIO() if quiet else sys.stdout.buffer # Generate the report reporter.generate_report(output_file) return reporter.total_percent_covered()
def test_violations(self): # Construct the XML report file_paths = ['file1.py', 'subdir/file2.py'] violations = self.MANY_VIOLATIONS measured = self.FEW_MEASURED xml = self._coverage_xml(file_paths, violations, measured) # Parse the report coverage = XmlCoverageReporter(xml) # Expect that the name is set self.assertEqual(coverage.name(), "XML") # By construction, each file has the same set # of covered/uncovered lines self.assertEqual(violations, coverage.violations('file1.py')) self.assertEqual(measured, coverage.measured_lines('file1.py')) # Try getting a smaller range result = coverage.violations('subdir/file2.py') self.assertEqual(result, violations) # Once more on the first file (for caching) result = coverage.violations('file1.py') self.assertEqual(result, violations)
def generate_coverage_report(coverage_xml, compare_branch, html_report=None, css_file=None, ignore_staged=False, ignore_unstaged=False, exclude=None): """ Generate the diff coverage report, using kwargs from `parse_args()`. """ diff = GitDiffReporter(compare_branch, git_diff=GitDiffTool(), ignore_staged=ignore_staged, ignore_unstaged=ignore_unstaged, exclude=exclude) xml_roots = [cElementTree.parse(xml_root) for xml_root in coverage_xml] clover_xml_roots = [ clover_xml for clover_xml in xml_roots if clover_xml.findall('.[@clover]') ] cobertura_xml_roots = [ cobertura_xml for cobertura_xml in xml_roots if cobertura_xml.findall('.[@line-rate]') ] if clover_xml_roots and cobertura_xml_roots: raise TypeError("Can't handle mixed coverage reports") elif clover_xml_roots: coverage = CloverXmlCoverageReporter(clover_xml_roots) elif cobertura_xml_roots: coverage = XmlCoverageReporter(cobertura_xml_roots) # Build a report generator if html_report is not None: css_url = css_file if css_url is not None: css_url = os.path.relpath(css_file, os.path.dirname(html_report)) reporter = HtmlReportGenerator(coverage, diff, css_url=css_url) with open(html_report, "wb") as output_file: reporter.generate_report(output_file) if css_file is not None: with open(css_file, "wb") as output_file: reporter.generate_css(output_file) reporter = StringReportGenerator(coverage, diff) output_file = sys.stdout if six.PY2 else sys.stdout.buffer # Generate the report reporter.generate_report(output_file) return reporter.total_percent_covered()
def test_non_python_violations(self): """ Non python projects often just have a file name specified while the full path can be acquired from a sources tag in the XML. This test checks that flow by requesting violation info from a path that can only be constructed by using the path provided in the sources tag """ fancy_path = 'superFancyPath' file_paths = ['file1.java'] source_paths = [fancy_path] violations = self.MANY_VIOLATIONS measured = self.FEW_MEASURED xml = self._coverage_xml( file_paths, violations, measured, source_paths=source_paths ) coverage = XmlCoverageReporter([xml]) self.assertEqual( violations, coverage.violations( '{0}/{1}'.format(fancy_path, file_paths[0]) ) ) self.assertEqual( measured, coverage.measured_lines( '{0}/{1}'.format(fancy_path, file_paths[0]) ) )
def generate_coverage_report(coverage_xml, compare_branch, html_report=None, css_file=None, json_report=None, ignore_staged=False, ignore_unstaged=False, exclude=None, src_roots=None, diff_range_notation=None, target_dir=None, diff_json=None): """ Generate the diff coverage report, using kwargs from `parse_args()`. """ if target_dir: class FileDiffReporter(GitDiffReporter): def __init__(self, *args, **kwargs): self.target_dir = kwargs.pop("td") super(FileDiffReporter, self).__init__(*args, **kwargs) def _git_diff(self): def compare(left, right): d = difile.Difile() result = d.compare_dir(left, right) diff_result = dict() for each_file in result: if not each_file: continue key = each_file[0].file_path.as_posix() if key.startswith(str(self.target_dir)): key = key.replace(str(self.target_dir) + "/", "") if key not in diff_result: diff_result[key] = [] for each_line in each_file: diff_result[key].append(each_line.line_no) return diff_result return compare(src_roots[0], self.target_dir) diff = FileDiffReporter( compare_branch, git_diff=GitDiffTool(diff_range_notation), ignore_staged=ignore_staged, ignore_unstaged=ignore_unstaged, exclude=exclude, td=target_dir) else: diff = GitDiffReporter( compare_branch, git_diff=GitDiffTool(diff_range_notation), ignore_staged=ignore_staged, ignore_unstaged=ignore_unstaged, exclude=exclude) xml_roots = [etree.parse(xml_root) for xml_root in coverage_xml] coverage = XmlCoverageReporter(xml_roots, src_roots) if diff_json: diff_dict = diff._git_diff() with open(diff_json, "w") as f: json.dump(diff_dict, f) # Build a report generator if html_report is not None: css_url = css_file if css_url is not None: css_url = os.path.relpath(css_file, os.path.dirname(html_report)) reporter = HtmlReportGenerator(coverage, diff, css_url=css_url) with open(html_report, "wb") as output_file: reporter.generate_report(output_file) if css_file is not None: with open(css_file, "wb") as output_file: reporter.generate_css(output_file) elif json_report is not None: reporter = JsonReportGenerator(coverage, diff) with open(json_report, "wb") as output_file: reporter.generate_report(output_file) reporter = StringReportGenerator(coverage, diff) output_file = sys.stdout if six.PY2 else sys.stdout.buffer # Generate the report reporter.generate_report(output_file) return reporter.total_percent_covered()