diff options
author | reybog90 <reybog90@o2.pl> | 2019-10-30 20:04:20 +0100 |
---|---|---|
committer | Ned Batchelder <ned@nedbatchelder.com> | 2019-11-01 06:36:13 -0400 |
commit | 9b11268c358040abf7384702c3bc0e863ab753c5 (patch) | |
tree | e657af6f7eb583354f41c455bee639aaaf9a39fa | |
parent | 49e06d33ea63d8e3e44ab5b69d713783551dfaa9 (diff) | |
download | python-coveragepy-git-9b11268c358040abf7384702c3bc0e863ab753c5.tar.gz |
Optionally skip empty files in reports
-rw-r--r-- | coverage/cmdline.py | 9 | ||||
-rw-r--r-- | coverage/config.py | 2 | ||||
-rw-r--r-- | coverage/control.py | 11 | ||||
-rw-r--r-- | coverage/html.py | 6 | ||||
-rw-r--r-- | coverage/summary.py | 9 | ||||
-rw-r--r-- | doc/config.rst | 5 | ||||
-rw-r--r-- | tests/test_api.py | 3 | ||||
-rw-r--r-- | tests/test_cmdline.py | 9 | ||||
-rw-r--r-- | tests/test_config.py | 2 | ||||
-rw-r--r-- | tests/test_html.py | 14 | ||||
-rw-r--r-- | tests/test_summary.py | 45 |
11 files changed, 110 insertions, 5 deletions
diff --git a/coverage/cmdline.py b/coverage/cmdline.py index 66d4dc3c..ef1184d0 100644 --- a/coverage/cmdline.py +++ b/coverage/cmdline.py @@ -93,6 +93,10 @@ class Opts(object): '--skip-covered', action='store_true', help="Skip files with 100% coverage.", ) + skip_empty = optparse.make_option( + '--skip-empty', action='store_true', + help="Skip empty files.", + ) show_contexts = optparse.make_option( '--show-contexts', action='store_true', help="Show contexts for covered lines.", @@ -203,6 +207,7 @@ class CoverageOptionParser(optparse.OptionParser, object): rcfile=True, show_missing=None, skip_covered=None, + skip_empty=None, show_contexts=None, source=None, timid=None, @@ -354,6 +359,7 @@ CMDS = { Opts.omit, Opts.title, Opts.skip_covered, + Opts.skip_empty, Opts.show_contexts, Opts.contexts, ] + GLOBAL_ARGS, @@ -375,6 +381,7 @@ CMDS = { Opts.contexts, Opts.show_missing, Opts.skip_covered, + Opts.skip_empty, ] + GLOBAL_ARGS, usage="[options] [modules]", description="Report coverage statistics on modules." @@ -575,6 +582,7 @@ class CoverageScript(object): total = self.coverage.report( show_missing=options.show_missing, skip_covered=options.skip_covered, + skip_empty=options.skip_empty, **report_args ) elif options.action == "annotate": @@ -584,6 +592,7 @@ class CoverageScript(object): directory=options.directory, title=options.title, skip_covered=options.skip_covered, + skip_empty=options.skip_empty, show_contexts=options.show_contexts, **report_args ) diff --git a/coverage/config.py b/coverage/config.py index 7d691145..c6689d2d 100644 --- a/coverage/config.py +++ b/coverage/config.py @@ -205,6 +205,7 @@ class CoverageConfig(object): self.report_contexts = None self.show_missing = False self.skip_covered = False + self.skip_empty = False # Defaults for [html] self.extra_css = None @@ -362,6 +363,7 @@ class CoverageConfig(object): ('report_omit', 'report:omit', 'list'), ('show_missing', 'report:show_missing', 'boolean'), ('skip_covered', 'report:skip_covered', 'boolean'), + ('skip_empty', 'report:skip_empty', 'boolean'), ('sort', 'report:sort'), # [html] diff --git a/coverage/control.py b/coverage/control.py index 7be28413..ff015882 100644 --- a/coverage/control.py +++ b/coverage/control.py @@ -774,7 +774,7 @@ class Coverage(object): def report( self, morfs=None, show_missing=None, ignore_errors=None, file=None, omit=None, include=None, skip_covered=None, - contexts=None, + contexts=None, skip_empty=None, ): """Write a textual summary report to `file`. @@ -794,6 +794,9 @@ class Coverage(object): If `skip_covered` is true, don't report on files with 100% coverage. + If `skip_empty` is true, don't report on empty files (those that have + no statements). + `contexts` is a list of regular expressions. Only data from :ref:`dynamic contexts <dynamic_contexts>` that match one of those expressions (using :func:`re.search <python:re.search>`) will be @@ -815,7 +818,7 @@ class Coverage(object): self, ignore_errors=ignore_errors, report_omit=omit, report_include=include, show_missing=show_missing, skip_covered=skip_covered, - report_contexts=contexts, + report_contexts=contexts, skip_empty=skip_empty, ): reporter = SummaryReporter(self) return reporter.report(morfs, outfile=file) @@ -843,7 +846,8 @@ class Coverage(object): def html_report(self, morfs=None, directory=None, ignore_errors=None, omit=None, include=None, extra_css=None, title=None, - skip_covered=None, show_contexts=None, contexts=None): + skip_covered=None, show_contexts=None, contexts=None, + skip_empty=None): """Generate an HTML report. The HTML is written to `directory`. The file "index.html" is the @@ -871,6 +875,7 @@ class Coverage(object): ignore_errors=ignore_errors, report_omit=omit, report_include=include, html_dir=directory, extra_css=extra_css, html_title=title, skip_covered=skip_covered, show_contexts=show_contexts, report_contexts=contexts, + skip_empty=skip_empty, ): reporter = HtmlReporter(self) return reporter.report(morfs) diff --git a/coverage/html.py b/coverage/html.py index 4a0e1a33..e3b814c5 100644 --- a/coverage/html.py +++ b/coverage/html.py @@ -282,6 +282,12 @@ class HtmlReporter(object): file_be_gone(html_path) return + if self.config.skip_empty: + # Don't report on empty files. + if nums.n_statements == 0: + file_be_gone(html_path) + return + # Find out if the file on disk is already correct. if self.incr.can_skip_file(self.data, fr, rootname): self.file_summaries.append(self.incr.index_info(rootname)) diff --git a/coverage/summary.py b/coverage/summary.py index 08c8a947..97d9fff0 100644 --- a/coverage/summary.py +++ b/coverage/summary.py @@ -21,6 +21,7 @@ class SummaryReporter(object): self.outfile = None self.fr_analysis = [] self.skipped_count = 0 + self.empty_count = 0 self.total = Numbers() self.fmt_err = u"%s %s: %s" @@ -48,6 +49,7 @@ class SummaryReporter(object): max_name = max([len(fr.relative_filename()) for (fr, analysis) in self.fr_analysis] + [5]) fmt_name = u"%%- %ds " % max_name fmt_skip_covered = u"\n%s file%s skipped due to complete coverage." + fmt_skip_empty = u"\n%s empty file%s skipped." header = (fmt_name % "Name") + u" Stmts Miss" fmt_coverage = fmt_name + u"%6d %6d" @@ -129,6 +131,10 @@ class SummaryReporter(object): self.writeout( fmt_skip_covered % (self.skipped_count, 's' if self.skipped_count > 1 else '') ) + if self.config.skip_empty and self.empty_count: + self.writeout( + fmt_skip_empty % (self.empty_count, 's' if self.empty_count > 1 else '') + ) return self.total.n_statements and self.total.pc_covered @@ -142,5 +148,8 @@ class SummaryReporter(object): if self.config.skip_covered and no_missing_lines and no_missing_branches: # Don't report on 100% files. self.skipped_count += 1 + elif self.config.skip_empty and nums.n_statements == 0: + # Don't report on empty files. + self.empty_count += 1 else: self.fr_analysis.append((fr, analysis)) diff --git a/doc/config.rst b/doc/config.rst index e332f50a..d7623532 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -294,6 +294,11 @@ missing lines. See :ref:`cmd_summary` for more information. ``skip_covered`` (boolean, default False): Don't include files in the report that are 100% covered files. See :ref:`cmd_summary` for more information. +.. _config_report_skip_empty: + +``skip_empty`` (boolean, default False): Don't include empty files (those that +have 0 statements) in the report. See :ref:`cmd_summary` for more information. + .. _config_report_sort: ``sort`` (string, default "Name"): Sort the text report by the named column. diff --git a/tests/test_api.py b/tests/test_api.py index b2143548..6455d097 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -904,7 +904,8 @@ class TestRunnerPluginTest(CoverageTest): cov.combine() cov.save() report = StringIO() - cov.report(show_missing=None, ignore_errors=True, file=report, skip_covered=None) + cov.report(show_missing=None, ignore_errors=True, file=report, skip_covered=None, + skip_empty=None) self.assertEqual(report.getvalue(), textwrap.dedent("""\ Name Stmts Miss Cover ----------------------------- diff --git a/tests/test_cmdline.py b/tests/test_cmdline.py index 26624b19..666327c8 100644 --- a/tests/test_cmdline.py +++ b/tests/test_cmdline.py @@ -37,10 +37,11 @@ class BaseCmdLineTest(CoverageTest): _defaults.Coverage().html_report( directory=None, ignore_errors=None, include=None, omit=None, morfs=[], skip_covered=None, show_contexts=None, title=None, contexts=None, + skip_empty=None, ) _defaults.Coverage().report( ignore_errors=None, include=None, omit=None, morfs=[], - show_missing=None, skip_covered=None, contexts=None, + show_missing=None, skip_covered=None, contexts=None, skip_empty=None, ) _defaults.Coverage().xml_report( ignore_errors=None, include=None, omit=None, morfs=[], outfile=None, @@ -261,6 +262,7 @@ class CmdLineTest(BaseCmdLineTest): out = self.stdout() self.assertIn("cover_pylib:", out) self.assertIn("skip_covered:", out) + self.assertIn("skip_empty:", out) def test_erase(self): # coverage erase @@ -370,6 +372,11 @@ class CmdLineTest(BaseCmdLineTest): cov.load() cov.report(skip_covered=True) """) + self.cmd_executes("report --skip-empty", """\ + cov = Coverage() + cov.load() + cov.report(skip_empty=True) + """) self.cmd_executes("report --contexts=foo,bar", """\ cov = Coverage() cov.load() diff --git a/tests/test_config.py b/tests/test_config.py index ebea18a7..fcbac816 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -311,6 +311,7 @@ class ConfigFileTest(UsingModulesMixin, CoverageTest): show_missing= TruE skip_covered = TruE + skip_empty =TruE [{section}html] @@ -386,6 +387,7 @@ class ConfigFileTest(UsingModulesMixin, CoverageTest): self.assertEqual(cov.config.plugins, ["plugins.a_plugin", "plugins.another"]) self.assertTrue(cov.config.show_missing) self.assertTrue(cov.config.skip_covered) + self.assertTrue(cov.config.skip_empty) self.assertEqual(cov.config.html_dir, r"c:\tricky\dir.somewhere") self.assertEqual(cov.config.extra_css, "something/extra.css") self.assertEqual(cov.config.html_title, "Title & nums # nums!") diff --git a/tests/test_html.py b/tests/test_html.py index 77e068d0..74cc15d9 100644 --- a/tests/test_html.py +++ b/tests/test_html.py @@ -533,6 +533,20 @@ class HtmlTest(HtmlTestHelpers, CoverageTest): self.assert_doesnt_exist("htmlcov/main_file_py.html") self.assert_exists("htmlcov/not_covered_py.html") + def test_report_skip_empty_files(self): + self.make_file("submodule/__init__.py", "") + self.make_file("main_file.py", """ + import submodule + + def normal(): + print("z") + normal() + """) + self.run_coverage(htmlargs=dict(skip_empty=True)) + self.assert_exists("htmlcov/index.html") + self.assert_exists("htmlcov/main_file_py.html") + self.assert_doesnt_exist("htmlcov/submodule___init___py.html") + class HtmlStaticFileTest(CoverageTest): """Tests of the static file copying for the HTML report.""" diff --git a/tests/test_summary.py b/tests/test_summary.py index b25c7764..01b6f9d0 100644 --- a/tests/test_summary.py +++ b/tests/test_summary.py @@ -431,6 +431,51 @@ class SummaryTest(UsingModulesMixin, CoverageTest): squeezed = self.squeezed_lines(report) self.assertEqual(squeezed[0], "No data to report.") + def test_report_skip_empty(self): + self.make_file("main.py", """ + import submodule + + def normal(): + print("z") + normal() + """) + self.make_file("submodule/__init__.py", "") + self.omit_site_packages() + out = self.run_command("coverage run main.py") + self.assertEqual(out, "z\n") + report = self.report_from_command("coverage report --skip-empty") + + # Name Stmts Miss Cover + # ------------------------------------ + # main.py 4 0 100% + # ------------------------------------ + # TOTAL 4 0 100% + # + # 1 empty file skipped. + + self.assertEqual(self.line_count(report), 7, report) + squeezed = self.squeezed_lines(report) + self.assertEqual(squeezed[2], "main.py 4 0 100%") + self.assertEqual(squeezed[4], "TOTAL 4 0 100%") + self.assertEqual(squeezed[6], "1 empty file skipped.") + self.assertEqual(self.last_command_status, 0) + + def test_report_skip_empty_no_data(self): + self.make_file("__init__.py", "") + self.omit_site_packages() + out = self.run_command("coverage run __init__.py") + self.assertEqual(out, "") + report = self.report_from_command("coverage report --skip-empty") + + # Name Stmts Miss Cover + # ------------------------------------ + # + # 1 empty file skipped. + + self.assertEqual(self.line_count(report), 4, report) + lines = self.report_lines(report) + self.assertEqual(lines[3], "1 empty file skipped.") + def test_report_precision(self): self.make_file(".coveragerc", """\ [report] |