diff options
author | Robert Collins <robertc@robertcollins.net> | 2014-08-24 17:54:36 +1200 |
---|---|---|
committer | Robert Collins <robertc@robertcollins.net> | 2014-08-24 17:54:36 +1200 |
commit | 19a32fbbc325bcb273c7d5f9b2f4e538a03e748d (patch) | |
tree | 26c1c2a01c0741680493d8e0196615a65a15099c | |
parent | 8215f60acf839cfd80d6d2ed78723b569c6a37f6 (diff) | |
download | subunit-19a32fbbc325bcb273c7d5f9b2f4e538a03e748d.tar.gz |
0.0.19
------
IMPROVEMENTS
~~~~~~~~~~~~
* ``subunit.run`` in Python will now exit 0 as long as the test stream has
been generated correctly - this has always been the intent but API friction
with testtools had prevented it working.
(Robert Collins)
-rw-r--r-- | NEWS | 19 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | python/subunit/__init__.py | 2 | ||||
-rwxr-xr-x | python/subunit/run.py | 42 | ||||
-rw-r--r-- | python/subunit/tests/test_run.py | 46 |
5 files changed, 80 insertions, 31 deletions
@@ -5,11 +5,22 @@ subunit release notes NEXT (In development) --------------------- +0.0.19 +------ + +IMPROVEMENTS +~~~~~~~~~~~~ + +* ``subunit.run`` in Python will now exit 0 as long as the test stream has + been generated correctly - this has always been the intent but API friction + with testtools had prevented it working. + (Robert Collins) + 0.0.18 ------ -IMPROVMENTS -~~~~~~~~~~~ +IMPROVEMENTS +~~~~~~~~~~~~ * Fix compatibility with testtools 0.9.35 which dropped the 'all' compat symbol. This breaks support for Python versions lower than 2.6. @@ -18,8 +29,8 @@ IMPROVMENTS 0.0.17 ------ -IMPROVMENTS -~~~~~~~~~~~ +IMPROVEMENTS +~~~~~~~~~~~~ * Add ``subunit-output`` tool that can generate a Subunit v2 bytestream from arguments passed on the command line. (Thomi Richards, #1252084) diff --git a/configure.ac b/configure.ac index 4c94519..07c96ac 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ m4_define([SUBUNIT_MAJOR_VERSION], [0]) m4_define([SUBUNIT_MINOR_VERSION], [0]) -m4_define([SUBUNIT_MICRO_VERSION], [18]) +m4_define([SUBUNIT_MICRO_VERSION], [19]) m4_define([SUBUNIT_VERSION], m4_defn([SUBUNIT_MAJOR_VERSION]).m4_defn([SUBUNIT_MINOR_VERSION]).m4_defn([SUBUNIT_MICRO_VERSION])) AC_PREREQ([2.59]) diff --git a/python/subunit/__init__.py b/python/subunit/__init__.py index 8764d45..ff952c3 100644 --- a/python/subunit/__init__.py +++ b/python/subunit/__init__.py @@ -153,7 +153,7 @@ from subunit.v2 import ByteStreamToStreamResult, StreamResultToBytes # If the releaselevel is 'final', then the tarball will be major.minor.micro. # Otherwise it is major.minor.micro~$(revno). -__version__ = (0, 0, 18, 'final', 0) +__version__ = (0, 0, 19, 'final', 0) PROGRESS_SET = 0 PROGRESS_CUR = 1 diff --git a/python/subunit/run.py b/python/subunit/run.py index 7e4d783..cf9cc01 100755 --- a/python/subunit/run.py +++ b/python/subunit/run.py @@ -40,15 +40,21 @@ from testtools.run import ( class SubunitTestRunner(object): - def __init__(self, verbosity=None, failfast=None, buffer=None, stream=None): + def __init__(self, verbosity=None, failfast=None, buffer=None, stream=None, + stdout=None): """Create a TestToolsTestRunner. :param verbosity: Ignored. :param failfast: Stop running tests at the first failure. :param buffer: Ignored. + :param stream: Upstream unittest stream parameter. + :param stdout: Testtools stream parameter. + + Either stream or stdout can be supplied, and stream will take + precedence. """ self.failfast = failfast - self.stream = stream or sys.stdout + self.stream = stream or stdout or sys.stdout def run(self, test): "Run the given test case or test suite." @@ -112,19 +118,27 @@ class SubunitTestProgram(TestProgram): sys.exit(2) -def main(): - # Disable the default buffering, for Python 2.x where pdb doesn't do it - # on non-ttys. - stream = get_default_formatter() +def main(argv=None, stdout=None): + if argv is None: + argv = sys.argv runner = SubunitTestRunner - # Patch stdout to be unbuffered, so that pdb works well on 2.6/2.7. - binstdout = io.open(sys.stdout.fileno(), 'wb', 0) - if sys.version_info[0] > 2: - sys.stdout = io.TextIOWrapper(binstdout, encoding=sys.stdout.encoding) - else: - sys.stdout = binstdout - SubunitTestProgram(module=None, argv=sys.argv, testRunner=runner, - stdout=sys.stdout) + # stdout is None except in unit tests. + if stdout is None: + stdout = sys.stdout + # XXX: This is broken code- SUBUNIT_FORMATTER is not being honoured. + stream = get_default_formatter() + # Disable the default buffering, for Python 2.x where pdb doesn't do it + # on non-ttys. + if hasattr(stdout, 'fileno'): + # Patch stdout to be unbuffered, so that pdb works well on 2.6/2.7. + binstdout = io.open(stdout.fileno(), 'wb', 0) + if sys.version_info[0] > 2: + sys.stdout = io.TextIOWrapper(binstdout, encoding=sys.stdout.encoding) + else: + sys.stdout = binstdout + stdout = sys.stdout + SubunitTestProgram(module=None, argv=argv, testRunner=runner, + stdout=stdout, exit=False) if __name__ == '__main__': diff --git a/python/subunit/tests/test_run.py b/python/subunit/tests/test_run.py index 6ac84e1..d92ed04 100644 --- a/python/subunit/tests/test_run.py +++ b/python/subunit/tests/test_run.py @@ -14,10 +14,12 @@ # limitations under that license. # -from testtools.compat import BytesIO +import io import unittest from testtools import PlaceHolder, TestCase +from testtools.compat import _b +from testtools.matchers import StartsWith from testtools.testresult.doubles import StreamResult import subunit @@ -28,37 +30,59 @@ from subunit.run import SubunitTestRunner class TestSubunitTestRunner(TestCase): def test_includes_timing_output(self): - io = BytesIO() - runner = SubunitTestRunner(stream=io) + bytestream = io.BytesIO() + runner = SubunitTestRunner(stream=bytestream) test = PlaceHolder('name') runner.run(test) - io.seek(0) + bytestream.seek(0) eventstream = StreamResult() - subunit.ByteStreamToStreamResult(io).run(eventstream) + subunit.ByteStreamToStreamResult(bytestream).run(eventstream) timestamps = [event[-1] for event in eventstream._events if event is not None] self.assertNotEqual([], timestamps) def test_enumerates_tests_before_run(self): - io = BytesIO() - runner = SubunitTestRunner(stream=io) + bytestream = io.BytesIO() + runner = SubunitTestRunner(stream=bytestream) test1 = PlaceHolder('name1') test2 = PlaceHolder('name2') case = unittest.TestSuite([test1, test2]) runner.run(case) - io.seek(0) + bytestream.seek(0) eventstream = StreamResult() - subunit.ByteStreamToStreamResult(io).run(eventstream) + subunit.ByteStreamToStreamResult(bytestream).run(eventstream) self.assertEqual([ ('status', 'name1', 'exists'), ('status', 'name2', 'exists'), ], [event[:3] for event in eventstream._events[:2]]) def test_list_errors_if_errors_from_list_test(self): - io = BytesIO() - runner = SubunitTestRunner(stream=io) + bytestream = io.BytesIO() + runner = SubunitTestRunner(stream=bytestream) def list_test(test): return [], ['failed import'] self.patch(run, 'list_test', list_test) exc = self.assertRaises(SystemExit, runner.list, None) self.assertEqual((2,), exc.args) + + class FailingTest(TestCase): + def test_fail(self): + 1/0 + + def test_exits_zero_when_tests_fail(self): + bytestream = io.BytesIO() + stream = io.TextIOWrapper(bytestream, encoding="utf8") + try: + self.assertEqual(None, run.main( + argv=["progName", "subunit.tests.test_run.TestSubunitTestRunner.FailingTest"], + stdout=stream)) + except SystemExit: + self.fail("SystemExit raised") + self.assertThat(bytestream.getvalue(), StartsWith(_b('\xb3'))) + + def test_exits_nonzero_when_execution_errors(self): + bytestream = io.BytesIO() + stream = io.TextIOWrapper(bytestream, encoding="utf8") + exc = self.assertRaises(Exception, run.main, + argv=["progName", "subunit.tests.test_run.TestSubunitTestRunner.MissingTest"], + stdout=stream) |