Commit 0c8e06d9286e06d888449052501a5dc432a3f2eb
1 parent
1e8e5737
unittest: create test util dir; move output capture there
Want to use the OutputCapture in another unit test. There will probably be more such test helpers over time that need to be imported from different unit tests.
Showing
3 changed files
with
54 additions
and
32 deletions
tests/msodde_doc/test_basic.py
| @@ -10,16 +10,10 @@ from __future__ import print_function | @@ -10,16 +10,10 @@ from __future__ import print_function | ||
| 10 | 10 | ||
| 11 | import unittest | 11 | import unittest |
| 12 | from oletools import msodde | 12 | from oletools import msodde |
| 13 | +from tests.test_utils import OutputCapture | ||
| 13 | import shlex | 14 | import shlex |
| 14 | from os.path import join, dirname, normpath | 15 | from os.path import join, dirname, normpath |
| 15 | -import sys | ||
| 16 | - | ||
| 17 | -# python 2/3 version conflict: | ||
| 18 | -if sys.version_info.major <= 2: | ||
| 19 | - from StringIO import StringIO | ||
| 20 | - #from io import BytesIO as StringIO - try if print() gives UnicodeError | ||
| 21 | -else: | ||
| 22 | - from io import StringIO | 16 | +from traceback import print_exc |
| 23 | 17 | ||
| 24 | 18 | ||
| 25 | # base directory for test input | 19 | # base directory for test input |
| @@ -74,6 +68,7 @@ class TestReturnCode(unittest.TestCase): | @@ -74,6 +68,7 @@ class TestReturnCode(unittest.TestCase): | ||
| 74 | return_code = msodde.main(args) | 68 | return_code = msodde.main(args) |
| 75 | except Exception: | 69 | except Exception: |
| 76 | have_exception = True | 70 | have_exception = True |
| 71 | + print_exc() | ||
| 77 | except SystemExit as se: # sys.exit() was called | 72 | except SystemExit as se: # sys.exit() was called |
| 78 | return_code = se.code | 73 | return_code = se.code |
| 79 | if se.code is None: | 74 | if se.code is None: |
| @@ -85,30 +80,6 @@ class TestReturnCode(unittest.TestCase): | @@ -85,30 +80,6 @@ class TestReturnCode(unittest.TestCase): | ||
| 85 | return_code)) | 80 | return_code)) |
| 86 | 81 | ||
| 87 | 82 | ||
| 88 | -class OutputCapture: | ||
| 89 | - """ context manager that captures stdout """ | ||
| 90 | - | ||
| 91 | - def __init__(self): | ||
| 92 | - self.output = StringIO() # in py2, this actually is BytesIO | ||
| 93 | - | ||
| 94 | - def __enter__(self): | ||
| 95 | - sys.stdout = self.output | ||
| 96 | - return self | ||
| 97 | - | ||
| 98 | - def __exit__(self, exc_type, exc_value, traceback): | ||
| 99 | - sys.stdout = sys.__stdout__ # re-set to original | ||
| 100 | - | ||
| 101 | - if exc_type: # there has been an error | ||
| 102 | - print('Got error during output capture!') | ||
| 103 | - print('Print captured output and re-raise:') | ||
| 104 | - for line in self.output.getvalue().splitlines(): | ||
| 105 | - print(line.rstrip()) # print output before re-raising | ||
| 106 | - | ||
| 107 | - def __iter__(self): | ||
| 108 | - for line in self.output.getvalue().splitlines(): | ||
| 109 | - yield line.rstrip() # remove newline at end of line | ||
| 110 | - | ||
| 111 | - | ||
| 112 | class TestDdeInDoc(unittest.TestCase): | 83 | class TestDdeInDoc(unittest.TestCase): |
| 113 | 84 | ||
| 114 | def get_dde_from_output(self, capturer): | 85 | def get_dde_from_output(self, capturer): |
tests/test_utils/__init__.py
0 → 100644
| 1 | +from .output_capture import OutputCapture |
tests/test_utils/output_capture.py
0 → 100644
| 1 | +""" class OutputCapture to test what scripts print to stdout """ | ||
| 2 | + | ||
| 3 | +from __future__ import print_function | ||
| 4 | +import sys | ||
| 5 | + | ||
| 6 | + | ||
| 7 | +# python 2/3 version conflict: | ||
| 8 | +if sys.version_info.major <= 2: | ||
| 9 | + from StringIO import StringIO | ||
| 10 | +else: | ||
| 11 | + from io import StringIO | ||
| 12 | + | ||
| 13 | +class OutputCapture: | ||
| 14 | + """ context manager that captures stdout | ||
| 15 | + | ||
| 16 | + use as follows:: | ||
| 17 | + | ||
| 18 | + with OutputCapture() as capturer: | ||
| 19 | + run_my_script(some_args) | ||
| 20 | + | ||
| 21 | + # either test line-by-line ... | ||
| 22 | + for line in capturer: | ||
| 23 | + some_test(line) | ||
| 24 | + # ...or test all output in one go | ||
| 25 | + some_test(capturer.buffer.getvalue()) | ||
| 26 | + | ||
| 27 | + """ | ||
| 28 | + | ||
| 29 | + def __init__(self): | ||
| 30 | + self.buffer = StringIO() | ||
| 31 | + self.orig_stdout = None | ||
| 32 | + | ||
| 33 | + def __enter__(self): | ||
| 34 | + # replace sys.stdout with own buffer. | ||
| 35 | + self.orig_stdout = sys.stdout | ||
| 36 | + sys.stdout = self.buffer | ||
| 37 | + return self | ||
| 38 | + | ||
| 39 | + def __exit__(self, exc_type, exc_value, traceback): | ||
| 40 | + sys.stdout = self.orig_stdout # re-set to original | ||
| 41 | + | ||
| 42 | + if exc_type: # there has been an error | ||
| 43 | + print('Got error during output capture!') | ||
| 44 | + print('Print captured output and re-raise:') | ||
| 45 | + for line in self.buffer.getvalue().splitlines(): | ||
| 46 | + print(line.rstrip()) # print output before re-raising | ||
| 47 | + | ||
| 48 | + def __iter__(self): | ||
| 49 | + for line in self.buffer.getvalue().splitlines(): | ||
| 50 | + yield line.rstrip() # remove newline at end of line |