summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorRobert Collins <robertc@robertcollins.net>2009-10-05 06:20:25 +1100
committerRobert Collins <robertc@robertcollins.net>2009-10-05 06:20:25 +1100
commitaa757dce0d1ca43a66a5f008e05699a0230b0d59 (patch)
tree15236c95ed2aebd00678d32cfdcb021a85e66713 /python
parent1bb81bd80c26f41555f676d9f6b164be9c061e61 (diff)
downloadsubunit-git-aa757dce0d1ca43a66a5f008e05699a0230b0d59.tar.gz
Hook addFailure to to details.
Diffstat (limited to 'python')
-rw-r--r--python/subunit/__init__.py62
-rw-r--r--python/subunit/content.py4
-rw-r--r--python/subunit/tests/test_test_protocol.py25
3 files changed, 71 insertions, 20 deletions
diff --git a/python/subunit/__init__.py b/python/subunit/__init__.py
index 4edd69d..9d021fe 100644
--- a/python/subunit/__init__.py
+++ b/python/subunit/__init__.py
@@ -46,8 +46,9 @@ will either lose fidelity (for instance, folding expected failures to success
in Python versions < 2.7 or 3.1), or discard the extended data (for extra
details, tags, timestamping and progress markers).
-The test outcome methods ``addSuccess`` take an optional keyword parameter
-``details`` which can be used instead of the usual python unittest parameter.
+The test outcome methods ``addSuccess``, ``addFailure`` take an optional
+keyword parameter ``details`` which can be used instead of the usual python
+unittest parameter.
When used the value of details should be a dict from ``string`` to
``subunit.content.Content`` objects. This is a draft API being worked on with
the Python Testing In Python mail list, with the goal of permitting a common
@@ -479,11 +480,28 @@ class TestProtocolClient(unittest.TestResult):
self._stream.write("%s\n" % line)
self._stream.write("]\n")
- def addFailure(self, test, error):
- """Report a failure in test test."""
- self._stream.write("failure: %s [\n" % test.id())
- for line in self._exc_info_to_string(error, test).splitlines():
- self._stream.write("%s\n" % line)
+ def addFailure(self, test, error=None, details=None):
+ """Report a failure in test test.
+
+ Only one of error and details should be provided: conceptually there
+ are two separate methods:
+ addFailure(self, test, error)
+ addFailure(self, test, details)
+
+ :param error: Standard unittest positional argument form - an
+ exc_info tuple.
+ :param details: New Testing-in-python drafted API; a dict from string
+ to subunit.Content objects.
+ """
+ self._stream.write("failure: %s" % test.id())
+ if error is None and details is None:
+ raise ValueError
+ if error is not None:
+ self._stream.write(" [\n")
+ for line in self._exc_info_to_string(error, test).splitlines():
+ self._stream.write("%s\n" % line)
+ else:
+ self._write_details(details)
self._stream.write("]\n")
def addSkip(self, test, reason):
@@ -498,14 +516,7 @@ class TestProtocolClient(unittest.TestResult):
if not details:
self._stream.write("\n")
else:
- self._stream.write(" [ multipart\n")
- for name, content in details.iteritems():
- self._stream.write("Content-Type: %s/%s\n" %
- (content.content_type.type, content.content_type.subtype))
- self._stream.write("%s\n" % name)
- for bytes in content.iter_bytes():
- self._stream.write("%d\n%s" % (len(bytes), bytes))
- self._stream.write("0\n")
+ self._write_details(details)
self._stream.write("]\n")
def startTest(self, test):
@@ -544,6 +555,27 @@ class TestProtocolClient(unittest.TestResult):
time.year, time.month, time.day, time.hour, time.minute,
time.second, time.microsecond))
+ def _write_details(self, details):
+ """Output details to the stream.
+
+ :param details: An extended details dict for a test outcome.
+ """
+ self._stream.write(" [ multipart\n")
+ for name, content in sorted(details.iteritems()):
+ self._stream.write("Content-Type: %s/%s" %
+ (content.content_type.type, content.content_type.subtype))
+ parameters = content.content_type.parameters
+ if parameters:
+ self._stream.write(";")
+ param_strs = []
+ for param, value in parameters.iteritems():
+ param_strs.append("%s=%s" % (param, value))
+ self._stream.write(",".join(param_strs))
+ self._stream.write("\n%s\n" % name)
+ for bytes in content.iter_bytes():
+ self._stream.write("%d\n%s" % (len(bytes), bytes))
+ self._stream.write("0\n")
+
def done(self):
"""Obey the testtools result.done() interface."""
diff --git a/python/subunit/content.py b/python/subunit/content.py
index cd3ad60..160a58a 100644
--- a/python/subunit/content.py
+++ b/python/subunit/content.py
@@ -63,5 +63,5 @@ class TracebackContent(Content):
{"language": "python"})
self._result = TestResult()
super(TracebackContent, self).__init__(content_type,
- lambda:self._result._exc_info_to_string(err,
- subunit.RemotedTestCase('')))
+ lambda:[self._result._exc_info_to_string(err,
+ subunit.RemotedTestCase(''))])
diff --git a/python/subunit/tests/test_test_protocol.py b/python/subunit/tests/test_test_protocol.py
index f505626..1b48290 100644
--- a/python/subunit/tests/test_test_protocol.py
+++ b/python/subunit/tests/test_test_protocol.py
@@ -21,7 +21,7 @@ import os
import sys
import subunit
-from subunit.content import Content
+from subunit.content import Content, TracebackContent
from subunit.content_type import ContentType
import subunit.iso8601 as iso8601
@@ -1056,6 +1056,9 @@ class TestTestProtocolClient(unittest.TestCase):
self.test = TestTestProtocolClient("test_start_test")
self.sample_details = {'something':Content(
ContentType('text', 'plain'), lambda:['serialised\nform'])}
+ self.sample_tb_details = dict(self.sample_details)
+ self.sample_tb_details['traceback'] = TracebackContent(
+ subunit.RemoteError("boo qux"))
def test_start_test(self):
"""Test startTest on a TestProtocolClient."""
@@ -1074,13 +1077,13 @@ class TestTestProtocolClient(unittest.TestCase):
self.io.getvalue(), "successful: %s\n" % self.test.id())
def test_add_success_details(self):
- """Test addSuccess on a TestProtocolClient."""
+ """Test addSuccess on a TestProtocolClient with details."""
self.protocol.addSuccess(self.test, details=self.sample_details)
self.assertEqual(
self.io.getvalue(), "successful: %s [ multipart\n"
"Content-Type: text/plain\n"
"something\n"
- "15\nserialised\nform0\n]\n"% self.test.id())
+ "15\nserialised\nform0\n]\n" % self.test.id())
def test_add_failure(self):
"""Test addFailure on a TestProtocolClient."""
@@ -1090,6 +1093,22 @@ class TestTestProtocolClient(unittest.TestCase):
self.io.getvalue(),
'failure: %s [\nRemoteException: boo qux\n]\n' % self.test.id())
+ def test_add_failure_details(self):
+ """Test addFailure on a TestProtocolClient with details."""
+ self.protocol.addFailure(
+ self.test, details=self.sample_tb_details)
+ self.assertEqual(
+ self.io.getvalue(),
+ "failure: %s [ multipart\n"
+ "Content-Type: text/plain\n"
+ "something\n"
+ "15\nserialised\nform0\n"
+ "Content-Type: text/x-traceback;language=python\n"
+ "traceback\n"
+ "25\nRemoteException: boo qux\n0\n"
+ "]\n" % self.test.id())
+
+
def test_add_error(self):
"""Test stopTest on a TestProtocolClient."""
self.protocol.addError(