diff options
| author | Robert Collins <robertc@robertcollins.net> | 2009-10-13 12:46:15 +1100 |
|---|---|---|
| committer | Robert Collins <robertc@robertcollins.net> | 2009-10-13 12:46:15 +1100 |
| commit | 129250bcfcdd915a1c8e71348efacdfda73d0594 (patch) | |
| tree | 0d00d904d55d83ef5a09693666fe3b275d49fa96 /python | |
| parent | 31a6e9bb2dcce48fe6aabe1cf6cd6bc566820b2f (diff) | |
| download | subunit-git-129250bcfcdd915a1c8e71348efacdfda73d0594.tar.gz | |
Move details parsing into a separate class.
Diffstat (limited to 'python')
| -rw-r--r-- | python/subunit/__init__.py | 36 | ||||
| -rw-r--r-- | python/subunit/details.py | 58 | ||||
| -rw-r--r-- | python/subunit/tests/__init__.py | 2 | ||||
| -rw-r--r-- | python/subunit/tests/test_details.py | 62 | ||||
| -rw-r--r-- | python/subunit/tests/test_test_protocol.py | 18 |
5 files changed, 158 insertions, 18 deletions
diff --git a/python/subunit/__init__.py b/python/subunit/__init__.py index c7edf6e..b4150a3 100644 --- a/python/subunit/__init__.py +++ b/python/subunit/__init__.py @@ -126,7 +126,7 @@ import unittest import iso8601 -import chunked, content, content_type +import chunked, content, content_type, details PROGRESS_SET = 0 @@ -256,11 +256,11 @@ class _InTest(_ParserState): self.parser._current_test = None elif self.parser.current_test_description + " [" == line[offset:-1]: self.parser._state = details_state - self.parser._message = "" + details_state.set_simple() elif self.parser.current_test_description + " [ multipart" == \ line[offset:-1]: self.parser._state = details_state - self.parser._message = "" + details_state.set_multipart() else: self.parser.stdOutLineReceived(line) @@ -330,7 +330,7 @@ class _OutSideTest(_ParserState): class _ReadingDetails(_ParserState): """Common logic for readin state details.""" - def _endQuote(self, line): + def endDetails(self): """The end of a details section has been reached.""" self.parser._state = self.parser._outside_test self.parser.current_test_description = None @@ -339,9 +339,7 @@ class _ReadingDetails(_ParserState): def lineReceived(self, line): """a line has been received.""" - if line == "]\n": - self._endQuote(line) - self.parser._appendMessage(line) + self.details_parser.lineReceived(line) def lostConnection(self): """Connection lost.""" @@ -352,13 +350,21 @@ class _ReadingDetails(_ParserState): """The label to describe this outcome.""" raise NotImplementedError(self._outcome_label) + def set_simple(self): + """Start a simple details parser.""" + self.details_parser = details.SimpleDetailsParser(self) + + def set_multipart(self): + """Start a multipart details parser.""" + self.details_parser = details.MultipartDetailsParser(self) + class _ReadingFailureDetails(_ReadingDetails): """State for the subunit parser when reading failure details.""" def _report_outcome(self): self.parser.client.addFailure(self.parser._current_test, - RemoteError(self.parser._message)) + RemoteError(self.details_parser.get_message())) def _outcome_label(self): return "failure" @@ -369,7 +375,7 @@ class _ReadingErrorDetails(_ReadingDetails): def _report_outcome(self): self.parser.client.addError(self.parser._current_test, - RemoteError(self.parser._message)) + RemoteError(self.details_parser.get_message())) def _outcome_label(self): return "error" @@ -381,7 +387,8 @@ class _ReadingExpectedFailureDetails(_ReadingDetails): def _report_outcome(self): xfail = getattr(self.parser.client, 'addExpectedFailure', None) if callable(xfail): - xfail(self.parser._current_test, RemoteError(self.parser._message)) + xfail(self.parser._current_test, + RemoteError(self.details_parser.get_message())) else: self.parser.client.addSuccess(self.parser._current_test) @@ -393,7 +400,7 @@ class _ReadingSkipDetails(_ReadingDetails): """State for the subunit parser when reading skip details.""" def _report_outcome(self): - self.parser._skip_or_error(self.parser._message) + self.parser._skip_or_error(self.details_parser.get_message()) def _outcome_label(self): return "skip" @@ -449,13 +456,6 @@ class TestProtocolServer(object): message = "No reason given" addSkip(self._current_test, message) - def _appendMessage(self, line): - if line[0:2] == " ]": - # quoted ] start - self._message += line[1:] - else: - self._message += line - def _handleProgress(self, offset, line): """Process a progress directive.""" line = line[offset:].strip() diff --git a/python/subunit/details.py b/python/subunit/details.py new file mode 100644 index 0000000..4f121cc --- /dev/null +++ b/python/subunit/details.py @@ -0,0 +1,58 @@ +# +# subunit: extensions to Python unittest to get test results from subprocesses. +# Copyright (C) 2005 Robert Collins <robertc@robertcollins.net> +# +# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause +# license at the users choice. A copy of both licenses are available in the +# project source as Apache-2.0 and BSD. You may not use this file except in +# compliance with one of these two licences. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# license you chose for the specific language governing permissions and +# limitations under that license. +# + +"""Handlers for outcome details.""" + +class DetailsParser(object): + """Base class/API reference for details parsing.""" + + +class SimpleDetailsParser(DetailsParser): + """Parser for single-part [] delimited details.""" + + def __init__(self, state): + self._message = "" + self._state = state + + def lineReceived(self, line): + if line == "]\n": + self._state.endDetails() + return + if line[0:2] == " ]": + # quoted ] start + self._message += line[1:] + else: + self._message += line + + def get_details(self): + return None + + def get_message(self): + return self._message + + +class MultipartDetailsParser(DetailsParser): + """Parser for multi-part [] surrounded MIME typed chunked details.""" + + def __init__(self, state): + self._state = state + self._details = {} + + def get_details(self): + return self._details + + def get_message(self): + return None diff --git a/python/subunit/tests/__init__.py b/python/subunit/tests/__init__.py index 8869425..fa31d68 100644 --- a/python/subunit/tests/__init__.py +++ b/python/subunit/tests/__init__.py @@ -19,6 +19,7 @@ from subunit.tests import ( test_chunked, test_content_type, test_content, + test_details, test_progress_model, test_subunit_filter, test_subunit_stats, @@ -33,6 +34,7 @@ def test_suite(): result.addTest(test_chunked.test_suite()) result.addTest(test_content_type.test_suite()) result.addTest(test_content.test_suite()) + result.addTest(test_details.test_suite()) result.addTest(test_progress_model.test_suite()) result.addTest(test_test_results.test_suite()) result.addTest(test_test_protocol.test_suite()) diff --git a/python/subunit/tests/test_details.py b/python/subunit/tests/test_details.py new file mode 100644 index 0000000..bc0930a --- /dev/null +++ b/python/subunit/tests/test_details.py @@ -0,0 +1,62 @@ +# +# subunit: extensions to python unittest to get test results from subprocesses. +# Copyright (C) 2005 Robert Collins <robertc@robertcollins.net> +# +# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause +# license at the users choice. A copy of both licenses are available in the +# project source as Apache-2.0 and BSD. You may not use this file except in +# compliance with one of these two licences. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# license you chose for the specific language governing permissions and +# limitations under that license. +# + +from cStringIO import StringIO +import unittest + +import subunit.tests +from subunit import details + + +def test_suite(): + loader = subunit.tests.TestUtil.TestLoader() + result = loader.loadTestsFromName(__name__) + return result + + +class TestSimpleDetails(unittest.TestCase): + + def test_lineReceived(self): + parser = details.SimpleDetailsParser(None) + parser.lineReceived("foo\n") + parser.lineReceived("bar\n") + self.assertEqual("foo\nbar\n", parser._message) + + def test_lineReceived_escaped_bracket(self): + parser = details.SimpleDetailsParser(None) + parser.lineReceived("foo\n") + parser.lineReceived(" ]are\n") + parser.lineReceived("bar\n") + self.assertEqual("foo\n]are\nbar\n", parser._message) + + def test_get_message(self): + parser = details.SimpleDetailsParser(None) + self.assertEqual("", parser.get_message()) + + def test_get_details_is_None(self): + parser = details.SimpleDetailsParser(None) + self.assertEqual(None, parser.get_details()) + + +class TestMultipartDetails(unittest.TestCase): + + def test_get_message_is_None(self): + parser = details.MultipartDetailsParser(None) + self.assertEqual(None, parser.get_message()) + + def test_get_details(self): + parser = details.MultipartDetailsParser(None) + self.assertEqual({}, parser.get_details()) diff --git a/python/subunit/tests/test_test_protocol.py b/python/subunit/tests/test_test_protocol.py index ac8733d..0994c54 100644 --- a/python/subunit/tests/test_test_protocol.py +++ b/python/subunit/tests/test_test_protocol.py @@ -453,6 +453,24 @@ class TestTestProtocolServerLostConnection(unittest.TestCase): self.do_connection_lost("xfail", "[ multipart\n") +class TestInTestMultipart(unittest.TestCase): + + def setUp(self): + self.client = MockTestProtocolServerClient() + self.protocol = subunit.TestProtocolServer(self.client) + self.protocol.lineReceived("test mcdonalds farm\n") + self.test = subunit.RemotedTestCase("mcdonalds farm") + + def test__outcome_sets_details_parser(self): + self.protocol._reading_success_details.details_parser = None + self.protocol._state._outcome(0, "mcdonalds farm [ multipart\n", + None, self.protocol._reading_success_details) + parser = self.protocol._reading_success_details.details_parser + self.assertNotEqual(None, parser) + self.assertTrue(isinstance(parser, + subunit.details.MultipartDetailsParser)) + + class TestTestProtocolServerAddError(unittest.TestCase): def setUp(self): |
