diff options
-rw-r--r-- | coverage/cmdline.py | 27 | ||||
-rw-r--r-- | doc/cmd.rst | 5 | ||||
-rw-r--r-- | test/test_process.py | 33 |
3 files changed, 58 insertions, 7 deletions
diff --git a/coverage/cmdline.py b/coverage/cmdline.py index 1ce5e0f5..59ef183d 100644 --- a/coverage/cmdline.py +++ b/coverage/cmdline.py @@ -20,10 +20,13 @@ class Opts(object): help="Measure branch coverage in addition to statement coverage." ) directory = optparse.make_option( - '-d', '--directory', action='store', - metavar="DIR", + '-d', '--directory', action='store', metavar="DIR", help="Write the output files to DIR." ) + fail_under = optparse.make_option( + '', '--fail-under', action='store', metavar="MIN", type="int", + help="Exit with a status of 2 if the total coverage is less than MIN." + ) help = optparse.make_option( '-h', '--help', action='store_true', help="Get help on this command." @@ -111,6 +114,7 @@ class CoverageOptionParser(optparse.OptionParser, object): actions=[], branch=None, directory=None, + fail_under=None, help=None, ignore_errors=None, include=None, @@ -273,6 +277,7 @@ CMDS = { 'html': CmdOptionParser("html", [ Opts.directory, + Opts.fail_under, Opts.ignore_errors, Opts.omit, Opts.include, @@ -285,6 +290,7 @@ CMDS = { 'report': CmdOptionParser("report", [ + Opts.fail_under, Opts.ignore_errors, Opts.omit, Opts.include, @@ -314,6 +320,7 @@ CMDS = { 'xml': CmdOptionParser("xml", [ + Opts.fail_under, Opts.ignore_errors, Opts.omit, Opts.include, @@ -327,7 +334,7 @@ CMDS = { } -OK, ERR = 0, 1 +OK, ERR, FAIL_UNDER = 0, 1, 2 class CoverageScript(object): @@ -539,19 +546,25 @@ class CoverageScript(object): ) if 'report' in options.actions: - self.coverage.report( + total = self.coverage.report( show_missing=options.show_missing, **report_args) if 'annotate' in options.actions: self.coverage.annotate( directory=options.directory, **report_args) if 'html' in options.actions: - self.coverage.html_report( + total = self.coverage.html_report( directory=options.directory, **report_args) if 'xml' in options.actions: outfile = options.outfile - self.coverage.xml_report(outfile=outfile, **report_args) + total = self.coverage.xml_report(outfile=outfile, **report_args) - return OK + if options.fail_under is not None: + if total >= options.fail_under: + return OK + else: + return FAIL_UNDER + else: + return OK def unshell_list(s): diff --git a/doc/cmd.rst b/doc/cmd.rst index 45552089..c15857cf 100644 --- a/doc/cmd.rst +++ b/doc/cmd.rst @@ -204,6 +204,11 @@ encountered trying to find source files to report on. This can be useful if some files are missing, or if your Python execution is tricky enough that file names are synthesized without real source files. +If you provide a ``--fail-under`` value, the total percentage covered will be +compared to that value. If it is less, the command will exit with a status +code of 2, indicating that the total coverage was less than your target. This +can be used as part of a pass/fail condition, for example in a continuous +integration server. This option isn't available for **annotate**. .. _cmd_summary: diff --git a/test/test_process.py b/test/test_process.py index f8d1b8d1..9f8aacca 100644 --- a/test/test_process.py +++ b/test/test_process.py @@ -382,3 +382,36 @@ class ProcessTest(CoverageTest): # imported is 120 or so. Just running os.getenv executes # about 5. self.assertGreater(data.summary()['os.py'], 50) + +class FailUnderTest(CoverageTest): + """Tests of the --fail-under switch.""" + + def setUp(self): + super(FailUnderTest, self).setUp() + self.make_file("fifty.py", """\ + # I have 50% coverage! + a = 1 + if a > 2: + b = 3 + c = 4 + """) + status, out = self.run_command_status("coverage run fifty.py", 0) + self.assertEqual(status, 0) + + def test_report(self): + status, out = self.run_command_status("coverage report --fail-under=50", 0) + self.assertEqual(status, 0) + status, out = self.run_command_status("coverage report --fail-under=51", 2) + self.assertEqual(status, 2) + + def test_html_report(self): + status, out = self.run_command_status("coverage html --fail-under=50", 0) + self.assertEqual(status, 0) + status, out = self.run_command_status("coverage html --fail-under=51", 2) + self.assertEqual(status, 2) + + def test_xml_report(self): + status, out = self.run_command_status("coverage xml --fail-under=50", 0) + self.assertEqual(status, 0) + status, out = self.run_command_status("coverage xml --fail-under=51", 2) + self.assertEqual(status, 2) |