[3] | 1 | """ |
---|
| 2 | This plugin captures stdout during test execution. If the test fails |
---|
| 3 | or raises an error, the captured output will be appended to the error |
---|
| 4 | or failure output. It is enabled by default but can be disabled with |
---|
| 5 | the options ``-s`` or ``--nocapture``. |
---|
| 6 | |
---|
| 7 | :Options: |
---|
| 8 | ``--nocapture`` |
---|
| 9 | Don't capture stdout (any stdout output will be printed immediately) |
---|
| 10 | |
---|
| 11 | """ |
---|
| 12 | import logging |
---|
| 13 | import os |
---|
| 14 | import sys |
---|
| 15 | from nose.plugins.base import Plugin |
---|
| 16 | from nose.util import ln |
---|
| 17 | from StringIO import StringIO |
---|
| 18 | |
---|
| 19 | |
---|
| 20 | log = logging.getLogger(__name__) |
---|
| 21 | |
---|
| 22 | class Capture(Plugin): |
---|
| 23 | """ |
---|
| 24 | Output capture plugin. Enabled by default. Disable with ``-s`` or |
---|
| 25 | ``--nocapture``. This plugin captures stdout during test execution, |
---|
| 26 | appending any output captured to the error or failure output, |
---|
| 27 | should the test fail or raise an error. |
---|
| 28 | """ |
---|
| 29 | enabled = True |
---|
| 30 | env_opt = 'NOSE_NOCAPTURE' |
---|
| 31 | name = 'capture' |
---|
| 32 | score = 500 |
---|
| 33 | |
---|
| 34 | def __init__(self): |
---|
| 35 | self.stdout = [] |
---|
| 36 | self._buf = None |
---|
| 37 | |
---|
| 38 | def options(self, parser, env): |
---|
| 39 | """Register commandline options |
---|
| 40 | """ |
---|
| 41 | parser.add_option( |
---|
| 42 | "-s", "--nocapture", action="store_false", |
---|
| 43 | default=not env.get(self.env_opt), dest="capture", |
---|
| 44 | help="Don't capture stdout (any stdout output " |
---|
| 45 | "will be printed immediately) [NOSE_NOCAPTURE]") |
---|
| 46 | |
---|
| 47 | def configure(self, options, conf): |
---|
| 48 | """Configure plugin. Plugin is enabled by default. |
---|
| 49 | """ |
---|
| 50 | self.conf = conf |
---|
| 51 | if not options.capture: |
---|
| 52 | self.enabled = False |
---|
| 53 | |
---|
| 54 | def afterTest(self, test): |
---|
| 55 | """Clear capture buffer. |
---|
| 56 | """ |
---|
| 57 | self.end() |
---|
| 58 | self._buf = None |
---|
| 59 | |
---|
| 60 | def begin(self): |
---|
| 61 | """Replace sys.stdout with capture buffer. |
---|
| 62 | """ |
---|
| 63 | self.start() # get an early handle on sys.stdout |
---|
| 64 | |
---|
| 65 | def beforeTest(self, test): |
---|
| 66 | """Flush capture buffer. |
---|
| 67 | """ |
---|
| 68 | self.start() |
---|
| 69 | |
---|
| 70 | def formatError(self, test, err): |
---|
| 71 | """Add captured output to error report. |
---|
| 72 | """ |
---|
| 73 | test.capturedOutput = output = self.buffer |
---|
| 74 | self._buf = None |
---|
| 75 | if not output: |
---|
| 76 | # Don't return None as that will prevent other |
---|
| 77 | # formatters from formatting and remove earlier formatters |
---|
| 78 | # formats, instead return the err we got |
---|
| 79 | return err |
---|
| 80 | ec, ev, tb = err |
---|
| 81 | return (ec, self.addCaptureToErr(ev, output), tb) |
---|
| 82 | |
---|
| 83 | def formatFailure(self, test, err): |
---|
| 84 | """Add captured output to failure report. |
---|
| 85 | """ |
---|
| 86 | return self.formatError(test, err) |
---|
| 87 | |
---|
| 88 | def addCaptureToErr(self, ev, output): |
---|
| 89 | return '\n'.join([str(ev) , ln('>> begin captured stdout <<'), |
---|
| 90 | output, ln('>> end captured stdout <<')]) |
---|
| 91 | |
---|
| 92 | def start(self): |
---|
| 93 | self.stdout.append(sys.stdout) |
---|
| 94 | self._buf = StringIO() |
---|
| 95 | sys.stdout = self._buf |
---|
| 96 | |
---|
| 97 | def end(self): |
---|
| 98 | if self.stdout: |
---|
| 99 | sys.stdout = self.stdout.pop() |
---|
| 100 | |
---|
| 101 | def finalize(self, result): |
---|
| 102 | """Restore stdout. |
---|
| 103 | """ |
---|
| 104 | while self.stdout: |
---|
| 105 | self.end() |
---|
| 106 | |
---|
| 107 | def _get_buffer(self): |
---|
| 108 | if self._buf is not None: |
---|
| 109 | return self._buf.getvalue() |
---|
| 110 | |
---|
| 111 | buffer = property(_get_buffer, None, None, |
---|
| 112 | """Captured stdout output.""") |
---|