From 49c15be1d5606d1255d2384f1f4876bd1a66a634 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Wed, 25 Nov 2009 18:08:57 +0100 Subject: * move pytest_coverage/nose_plugin to become directly importable * fixing order of coverage options * pytest: only do coverage-processing if cover-action is defined --- coverage/nose_coverage.py | 106 +++++++++++++++++++++++++++++ coverage/pytest_coverage.py | 74 +++++++++++++++++++++ coverage/runner.py | 60 ++++++++--------- coverage/test_plugins/nose_coverage.py | 111 ------------------------------- coverage/test_plugins/pytest_coverage.py | 69 ------------------- 5 files changed, 210 insertions(+), 210 deletions(-) create mode 100644 coverage/nose_coverage.py create mode 100644 coverage/pytest_coverage.py delete mode 100644 coverage/test_plugins/nose_coverage.py delete mode 100644 coverage/test_plugins/pytest_coverage.py (limited to 'coverage') diff --git a/coverage/nose_coverage.py b/coverage/nose_coverage.py new file mode 100644 index 0000000..6ba0a10 --- /dev/null +++ b/coverage/nose_coverage.py @@ -0,0 +1,106 @@ +import logging +import unittest, os +from nose.plugins import Plugin, PluginTester + +import sys +import os +sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__), '../../'))) + +log = logging.getLogger(__name__) + + +class Coverage(Plugin): + """ + Activate a coverage report using Ned Batchelder's coverage module. + """ + + name = "coverage_new" + score = 1 + status = {} + + def options(self, parser, env): + """ + Add options to command line. + """ + Plugin.options(self, parser, env) + from coverage.runner import options + for opt in options: + parser.add_option(opt) + + def configure(self, options, config): + """ + Configure plugin. + """ + try: + self.status.pop('active') + except KeyError: + pass + Plugin.configure(self, options, config) + if self.enabled: + try: + import coverage + except ImportError: + log.error("Coverage not available: " + "unable to import coverage module") + self.enabled = False + return + + self.config = config + self.status['active'] = True + self.options = options + + def begin(self): + """ + Begin recording coverage information. + """ + log.debug("Coverage begin") + # Load the runner and start it up + from coverage.runner import CoverageTestWrapper + self.coverage = CoverageTestWrapper(self.options) + self.coverage.start() + + def report(self, stream): + """ + Output code coverage report. + """ + log.debug("Coverage report") + stream.write("Processing Coverage...") + # finish up with coverage + self.coverage.finish() + + +# Monkey patch omit_filter to use regex patterns for file omits +def omit_filter(omit_prefixes, code_units): + import re + exclude_patterns = [re.compile(line.strip()) for line in omit_prefixes if line and not line.startswith('#')] + filtered = [] + for cu in code_units: + skip = False + for pattern in exclude_patterns: + if pattern.search(cu.filename): + skip = True + break + + if not skip: + filtered.append(cu) + return filtered + +try: + import coverage + coverage.codeunit.omit_filter = omit_filter +except: + pass + +class TestCoverage(PluginTester, unittest.TestCase): + activate = '--with-coverage_new' # enables the plugin + plugins = [Coverage()] + args = ['--cover-action=report'] + + def test_output(self): + assert "Processing Coverage..." in self.output, ( + "got: %s" % self.output) + def makeSuite(self): + class TC(unittest.TestCase): + def runTest(self): + raise ValueError("Coverage down") + return unittest.TestSuite([TC()]) diff --git a/coverage/pytest_coverage.py b/coverage/pytest_coverage.py new file mode 100644 index 0000000..094be44 --- /dev/null +++ b/coverage/pytest_coverage.py @@ -0,0 +1,74 @@ +""" +Write and report coverage data with 'coverage.py'. +""" +import py +import coverage + +def pytest_addoption(parser): + """ + Get all the options from the coverage.runner and import them + """ + from coverage.runner import options + group = parser.getgroup('Coverage options') + for opt in options: + group._addoption_instance(opt) + +def pytest_configure(config): + # Load the runner and start it up + if config.getvalue("cover_actions"): + config.pluginmanager.register(DoCover(config), "do_coverage") + +class DoCover: + def __init__(self, config): + self.config = config + + def pytest_sessionstart(self): + from coverage.runner import CoverageTestWrapper + self.coverage = CoverageTestWrapper(self.config.option) + # XXX maybe better to start/suspend/resume coverage + # for each single test item + self.coverage.start() + + def pytest_terminal_summary(self, terminalreporter): + # Finished the tests start processing the coverage + config = terminalreporter.config + tw = terminalreporter._tw + tw.sep('-', 'coverage') + tw.line('Processing Coverage...') + self.coverage.finish() + + +# Monkey patch omit_filter to use regex patterns for file omits +def omit_filter(omit_prefixes, code_units): + import re + exclude_patterns = [re.compile(line.strip()) for line in omit_prefixes if line and not line.startswith('#')] + filtered = [] + for cu in code_units: + skip = False + for pattern in exclude_patterns: + if pattern.search(cu.filename): + skip = True + break + + if not skip: + filtered.append(cu) + return filtered + +coverage.codeunit.omit_filter = omit_filter + +pytest_plugins = ['pytester'] +def test_functional(testdir): + testdir.makepyfile(""" + def f(): + x = 42 + def test_whatever(): + pass + """) + result = testdir.runpytest("--cover-action=annotate") + assert result.ret == 0 + assert result.stdout.fnmatch_lines([ + '*Processing Coverage*' + ]) + coveragefile = testdir.tmpdir.join(".coverage") + assert coveragefile.check() + # XXX try loading it? diff --git a/coverage/runner.py b/coverage/runner.py index ba4861a..ef4c1f2 100644 --- a/coverage/runner.py +++ b/coverage/runner.py @@ -73,66 +73,66 @@ class CoverageTestWrapper(object): return -class Options(object): - """A namespace class for individual options we'll build parsers from.""" - - action = optparse.Option('', +options = [ + optparse.Option('', '--cover-action', action='append', default=None, dest='cover_actions', type="choice", choices=['annotate', 'html', 'report', 'xml'], - help=""" - annotate Annotate source files with execution information. - html Create an HTML report. - report Report coverage stats on modules. - xml Create an XML report of coverage results. - """.strip()) - - branch = optparse.Option( + help="""\ +annotate Annotate source files with execution information. +html Create an HTML report. +report Report coverage stats on modules. +xml Create an XML report of coverage results. +""".strip()), + + optparse.Option( '--cover-branch', action='store_true', help="Measure branch execution. HIGHLY EXPERIMENTAL!" - ) - directory = optparse.Option( + ), + optparse.Option( '--cover-directory', action='store', metavar="DIR", help="Write the output files to DIR." - ) - ignore_errors = optparse.Option( + ), + optparse.Option( '--cover-ignore-errors', action='store_true', help="Ignore errors while reading source files." - ) - pylib = optparse.Option( + ), + optparse.Option( '--cover-pylib', action='store_true', help="Measure coverage even inside the Python installed library, " "which isn't done by default." - ) - show_missing = optparse.Option( + ), + optparse.Option( '--cover-show-missing', action='store_true', help="Show line numbers of statements in each module that weren't " "executed." - ) - omit = optparse.Option( + ), + optparse.Option( '--cover-omit', action='store', metavar="PRE1,PRE2,...", default='', help="Omit files when their filename path starts with one of these " "prefixes." - ) - output_xml = optparse.Option( + ), + optparse.Option( '--cover-outfile', action='store', metavar="OUTFILE", help="Write the XML report to this file. Defaults to 'coverage.xml'" - ) - parallel_mode = optparse.Option( + ), + optparse.Option( '--cover-parallel-mode', action='store_true', help="Include the machine name and process id in the .coverage " "data file name." - ) - timid = optparse.Option( + ), + optparse.Option( '--cover-timid', action='store_true', help="Use a simpler but slower trace method. Try this if you get " "seemingly impossible results!" - ) - append = optparse.Option( + ), + optparse.Option( '--cover-append', action='store_false', help="Append coverage data to .coverage, otherwise it is started " "clean with each run." ) +] + diff --git a/coverage/test_plugins/nose_coverage.py b/coverage/test_plugins/nose_coverage.py deleted file mode 100644 index 603ce43..0000000 --- a/coverage/test_plugins/nose_coverage.py +++ /dev/null @@ -1,111 +0,0 @@ -import logging -import unittest, os -from nose.plugins import Plugin, PluginTester - -import sys -import os -sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__), '../../'))) - -log = logging.getLogger(__name__) - - -class Coverage(Plugin): - """ - Activate a coverage report using Ned Batchelder's coverage module. - """ - - name = "coverage_new" - score = 1 - status = {} - - def options(self, parser, env): - """ - Add options to command line. - """ - - Plugin.options(self, parser, env) - - from coverage.runner import Options - # Loop the coverage options and append them to the plugin options - options = [a for a in dir(Options) if not a.startswith('_')] - for option in options: - opt = getattr(Options, option) - parser.add_option(opt) - - def configure(self, options, config): - """ - Configure plugin. - """ - try: - self.status.pop('active') - except KeyError: - pass - Plugin.configure(self, options, config) - if self.enabled: - try: - import coverage - except ImportError: - log.error("Coverage not available: " - "unable to import coverage module") - self.enabled = False - return - - self.config = config - self.status['active'] = True - self.options = options - - def begin(self): - """ - Begin recording coverage information. - """ - log.debug("Coverage begin") - # Load the runner and start it up - from coverage.runner import CoverageTestWrapper - self.coverage = CoverageTestWrapper(self.options) - self.coverage.start() - - def report(self, stream): - """ - Output code coverage report. - """ - log.debug("Coverage report") - stream.write("Processing Coverage...") - # finish up with coverage - self.coverage.finish() - - -# Monkey patch omit_filter to use regex patterns for file omits -def omit_filter(omit_prefixes, code_units): - import re - exclude_patterns = [re.compile(line.strip()) for line in omit_prefixes if line and not line.startswith('#')] - filtered = [] - for cu in code_units: - skip = False - for pattern in exclude_patterns: - if pattern.search(cu.filename): - skip = True - break - - if not skip: - filtered.append(cu) - return filtered - -try: - import coverage - coverage.codeunit.omit_filter = omit_filter -except: - pass - -class TestCoverage(PluginTester, unittest.TestCase): - activate = '--with-coverage_new' # enables the plugin - plugins = [Coverage()] - args = ['--cover-action=report'] - - def test_output(self): - assert "Processing Coverage..." in self.output, ( - "got: %s" % self.output) - def makeSuite(self): - class TC(unittest.TestCase): - def runTest(self): - raise ValueError("Coverage down") - return unittest.TestSuite([TC()]) \ No newline at end of file diff --git a/coverage/test_plugins/pytest_coverage.py b/coverage/test_plugins/pytest_coverage.py deleted file mode 100644 index 5b910e9..0000000 --- a/coverage/test_plugins/pytest_coverage.py +++ /dev/null @@ -1,69 +0,0 @@ -""" -Write and report coverage data with 'coverage.py'. -""" -import py - -coverage = py.test.importorskip("coverage") - -def pytest_configure(config): - # Load the runner and start it up - from coverage.runner import CoverageTestWrapper - - config.coverage = CoverageTestWrapper(config.option) - config.coverage.start() - -def pytest_terminal_summary(terminalreporter): - # Finished the tests start processing the coverage - config = terminalreporter.config - tw = terminalreporter._tw - tw.sep('-', 'coverage') - tw.line('Processing Coverage...') - - # finish up with coverage - config.coverage.finish() - -def pytest_addoption(parser): - """ - Get all the options from the coverage.runner and import them - """ - from coverage.runner import Options - - group = parser.getgroup('Coverage options') - # Loop the coverage options and append them to the plugin options - options = [a for a in dir(Options) if not a.startswith('_')] - for option in options: - opt = getattr(Options, option) - group._addoption_instance(opt, shortupper=True) - -# Monkey patch omit_filter to use regex patterns for file omits -def omit_filter(omit_prefixes, code_units): - import re - exclude_patterns = [re.compile(line.strip()) for line in omit_prefixes if line and not line.startswith('#')] - filtered = [] - for cu in code_units: - skip = False - for pattern in exclude_patterns: - if pattern.search(cu.filename): - skip = True - break - - if not skip: - filtered.append(cu) - return filtered - -coverage.codeunit.omit_filter = omit_filter - -def test_functional(testdir): - py.test.importorskip("coverage") - testdir.plugins.append("coverage") - testdir.makepyfile(""" - def f(): - x = 42 - def test_whatever(): - pass - """) - result = testdir.runpytest() - assert result.ret == 0 - assert result.stdout.fnmatch_lines([ - '*Processing Coverage*' - ]) \ No newline at end of file -- cgit v1.2.1