Skip to content

Commit

Permalink
add total number of coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
zhangbiao11 committed Jul 13, 2020
1 parent 83f00c8 commit 4ff24f9
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 83 deletions.
41 changes: 16 additions & 25 deletions diff_cover/diff_cover_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@
from diff_cover.diff_reporter import GitDiffReporter
from diff_cover.git_diff import GitDiffTool
from diff_cover.git_path import GitPathTool
from diff_cover.report_generator import HtmlReportGenerator, StringReportGenerator, JsonReportGenerator
from diff_cover.report_generator import HtmlReportGenerator, StringReportGenerator
from diff_cover.violationsreporters.violations_reporter import XmlCoverageReporter

HTML_REPORT_HELP = "Diff coverage HTML output"
JSON_REPORT_HELP = "Diff coverage JSON output"
COMPARE_BRANCH_HELP = "Branch to compare"
CSS_FILE_HELP = "Write CSS into an external file"
FAIL_UNDER_HELP = "Returns an error code if coverage or quality score is below this value"
MIN_DIFF_LINE_HELP = "Ignore --fail-under if the changed lines in diff are less than this value"
IGNORE_STAGED_HELP = "Ignores staged changes"
IGNORE_UNSTAGED_HELP = "Ignores unstaged changes"
EXCLUDE_HELP = "Exclude files, more patterns supported"
Expand All @@ -44,11 +44,10 @@ def parse_coverage_args(argv):
{
'coverage_xml': COVERAGE_XML,
'html_report': None | HTML_REPORT,
'json_report': None | JSON_REPORT,
'external_css_file': None | CSS_FILE,
}
where `COVERAGE_XML`, `HTML_REPORT`, `JSON_REPORT`, and `CSS_FILE` are paths.
where `COVERAGE_XML`, `HTML_REPORT`, and `CSS_FILE` are paths.
The path strings may or may not exist.
"""
Expand All @@ -61,24 +60,14 @@ def parse_coverage_args(argv):
nargs='+'
)

output_format = parser.add_mutually_exclusive_group()

output_format.add_argument(
parser.add_argument(
'--html-report',
metavar='FILENAME',
type=str,
default=None,
help=HTML_REPORT_HELP
)

output_format.add_argument(
'--json-report',
metavar='FILENAME',
type=str,
default=None,
help=JSON_REPORT_HELP
)

parser.add_argument(
'--external-css-file',
metavar='FILENAME',
Expand All @@ -103,6 +92,14 @@ def parse_coverage_args(argv):
help=FAIL_UNDER_HELP
)

parser.add_argument(
'--min-diff-line',
metavar='SCORE',
type=int,
default='0',
help=MIN_DIFF_LINE_HELP
)

parser.add_argument(
'--ignore-staged',
action='store_true',
Expand Down Expand Up @@ -154,7 +151,6 @@ def parse_coverage_args(argv):

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):
"""
Expand All @@ -180,17 +176,12 @@ def generate_coverage_report(coverage_xml, compare_branch,
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()
return reporter.total_num_lines(), reporter.total_percent_covered()


def main(argv=None, directory=None):
Expand All @@ -207,11 +198,11 @@ def main(argv=None, directory=None):
arg_dict = parse_coverage_args(argv[1:])
GitPathTool.set_cwd(directory)
fail_under = arg_dict.get('fail_under')
percent_covered = generate_coverage_report(
min_diff_line = arg_dict.get('min_diff_line')
total_diff_line, percent_covered = generate_coverage_report(
arg_dict['coverage_xml'],
arg_dict['compare_branch'],
html_report=arg_dict['html_report'],
json_report=arg_dict['json_report'],
css_file=arg_dict['external_css_file'],
ignore_staged=arg_dict['ignore_staged'],
ignore_unstaged=arg_dict['ignore_unstaged'],
Expand All @@ -220,7 +211,7 @@ def main(argv=None, directory=None):
diff_range_notation=arg_dict['diff_range_notation']
)

if percent_covered >= fail_under:
if total_diff_line <= min_diff_line or percent_covered >= fail_under:
return 0
else:
LOGGER.error("Failure. Coverage is below {}%.".format(fail_under))
Expand Down
90 changes: 32 additions & 58 deletions diff_cover/report_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
from jinja2_pluralize import pluralize_dj
from diff_cover.snippets import Snippet
import six
import json


class DiffViolations(object):
Expand Down Expand Up @@ -168,44 +167,15 @@ def _diff_violations(self):
"""
if not self._diff_violations_dict:
self._diff_violations_dict = {
src_path: DiffViolations(
self._violations.violations(src_path),
self._violations.measured_lines(src_path),
self._diff.lines_changed(src_path),
)
for src_path in self._diff.src_paths_changed()
src_path: DiffViolations(
self._violations.violations(src_path),
self._violations.measured_lines(src_path),
self._diff.lines_changed(src_path),
)
for src_path in self._diff.src_paths_changed()
}
return self._diff_violations_dict

def report_dict(self):
src_stats = {
src: self._src_path_stats(src) for src in self.src_paths()
}

return {
'report_name': self.coverage_report_name(),
'diff_name': self.diff_report_name(),
'src_stats': src_stats,
'total_num_lines': self.total_num_lines(),
'total_num_violations': self.total_num_violations(),
'total_percent_covered': self.total_percent_covered(),
}

def _src_path_stats(self, src_path):
"""
Return a dict of statistics for the source file at `src_path`.
"""

# Find violation lines
violation_lines = self.violation_lines(src_path)
violations = sorted(self._diff_violations()[src_path].violations)

return {
'percent_covered': self.percent_covered(src_path),
'violation_lines': violation_lines,
'violations': violations,
}


# Set up the template environment
TEMPLATE_LOADER = PackageLoader(__package__)
Expand All @@ -216,15 +186,6 @@ def _src_path_stats(self, src_path):
TEMPLATE_ENV.filters['pluralize'] = pluralize_dj


class JsonReportGenerator(BaseReportGenerator):
def generate_report(self, output_file):
json_report_str = json.dumps(self.report_dict())

# all report generators are expected to write raw bytes, so we encode
# the json
output_file.write(json_report_str.encode('utf-8'))


class TemplateReportGenerator(BaseReportGenerator):
"""
Reporter that uses a template to generate the report.
Expand Down Expand Up @@ -293,20 +254,28 @@ def _context(self):
}
"""

# Calculate the information to pass to the template
src_stats = {
src: self._src_path_stats(src) for src in self.src_paths()
}

# Include snippet style info if we're displaying
# source code snippets
if self.INCLUDE_SNIPPETS:
snippet_style = Snippet.style_defs()
else:
snippet_style = None

context = super(TemplateReportGenerator, self).report_dict()
context.update({
return {
'css_url': self.css_url,
'report_name': self.coverage_report_name(),
'diff_name': self.diff_report_name(),
'src_stats': src_stats,
'total_num_lines': self.total_num_lines(),
'total_num_violations': self.total_num_violations(),
'total_percent_covered': self.total_percent_covered(),
'snippet_style': snippet_style
})

return context
}

@staticmethod
def combine_adjacent_lines(line_numbers):
Expand Down Expand Up @@ -338,25 +307,30 @@ def combine_adjacent_lines(line_numbers):
return combined_list

def _src_path_stats(self, src_path):
"""
Return a dict of statistics for the source file at `src_path`.
"""

stats = super(TemplateReportGenerator, self)._src_path_stats(src_path)
# Find violation lines
violation_lines = self.violation_lines(src_path)
violations = sorted(self._diff_violations()[src_path].violations)

# Load source snippets (if the report will display them)
# If we cannot load the file, then fail gracefully
if self.INCLUDE_SNIPPETS:
try:
snippets = Snippet.load_snippets_html(src_path, stats['violation_lines'])
snippets = Snippet.load_snippets_html(src_path, violation_lines)
except IOError:
snippets = []
else:
snippets = []

stats.update({
'snippets_html': snippets,
'violation_lines': TemplateReportGenerator.combine_adjacent_lines(stats['violation_lines']),
})

return stats
return {
'percent_covered': self.percent_covered(src_path),
'violation_lines': TemplateReportGenerator.combine_adjacent_lines(violation_lines),
'violations': violations,
'snippets_html': snippets
}


class StringReportGenerator(TemplateReportGenerator):
Expand Down

0 comments on commit 4ff24f9

Please sign in to comment.