summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Collins <robertc@robertcollins.net>2021-07-29 10:44:48 +0200
committerGitHub <noreply@github.com>2021-07-29 10:44:48 +0200
commitc87ffbd904627d777aa1430963dced92a36aa033 (patch)
treec7abf479a50a137f715e591e20805e3947a7f4e9
parent59fbca9f6c5b4095622460d7237c13998d848d97 (diff)
parentfaaca9b50f59d63a21663a1dc8ed21f22ffb6223 (diff)
downloadsubunit-git-c87ffbd904627d777aa1430963dced92a36aa033.tar.gz
Merge pull request #51 from cjwatson/testtools-2.5.0
Fix tests with testtools 2.5.0
-rw-r--r--NEWS6
-rw-r--r--python/subunit/__init__.py2
-rw-r--r--python/subunit/tests/__init__.py1
-rw-r--r--python/subunit/tests/test_test_protocol.py165
4 files changed, 106 insertions, 68 deletions
diff --git a/NEWS b/NEWS
index 73f660a..82c9f53 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,12 @@ subunit release notes
NEXT (In development)
---------------------
+BUGFIXES
+~~~~~~~~
+
+* Fix tests with testtools >= 2.5.0.
+ (Colin Watson)
+
1.4.0
-----
diff --git a/python/subunit/__init__.py b/python/subunit/__init__.py
index cf4692a..6917f42 100644
--- a/python/subunit/__init__.py
+++ b/python/subunit/__init__.py
@@ -821,7 +821,7 @@ class TestProtocolClient(testresult.TestResult):
if parameters:
self._stream.write(_b(";"))
param_strs = []
- for param, value in parameters.items():
+ for param, value in sorted(parameters.items()):
param_strs.append("%s=%s" % (param, value))
self._stream.write(_b(",".join(param_strs)))
self._stream.write(_b("\n%s\n" % name))
diff --git a/python/subunit/tests/__init__.py b/python/subunit/tests/__init__.py
index c6599f7..4c8b2ae 100644
--- a/python/subunit/tests/__init__.py
+++ b/python/subunit/tests/__init__.py
@@ -23,6 +23,7 @@ from testscenarios import generate_scenarios
# Before the test module imports to avoid circularity.
# For testing: different pythons have different str() implementations.
_remote_exception_repr = "testtools.testresult.real._StringException"
+_remote_exception_repr_chunked = "34\r\n" + _remote_exception_repr + ": boo qux\n0\r\n"
_remote_exception_str = "Traceback (most recent call last):\ntesttools.testresult.real._StringException"
_remote_exception_str_chunked = "57\r\n" + _remote_exception_str + ": boo qux\n0\r\n"
diff --git a/python/subunit/tests/test_test_protocol.py b/python/subunit/tests/test_test_protocol.py
index faab93e..70e3564 100644
--- a/python/subunit/tests/test_test_protocol.py
+++ b/python/subunit/tests/test_test_protocol.py
@@ -20,6 +20,7 @@ import os
import tempfile
import unittest
+import six
from testtools import PlaceHolder, skipIf, TestCase, TestResult
from testtools.compat import _b, _u
try:
@@ -40,12 +41,12 @@ except ImportError:
Python27TestResult,
ExtendedTestResult,
)
-from testtools.matchers import Contains
-from testtools.testcase import six
+from testtools.matchers import Contains, Equals, MatchesAny
import subunit
from subunit.tests import (
_remote_exception_repr,
+ _remote_exception_repr_chunked,
_remote_exception_str,
_remote_exception_str_chunked,
)
@@ -1194,6 +1195,11 @@ class TestIsolatedTestSuite(TestCase):
self.assertEqual(self.SampleTestToIsolate.TEST, False)
+# A number of these tests produce different output depending on the
+# testtools version. testtools < 2.5.0 used traceback2, which incorrectly
+# included the traceback header even for an exception with no traceback.
+# testtools 2.5.0 switched to the Python 3 standard library's traceback
+# module, which fixes this bug. See https://bugs.python.org/issue24695.
class TestTestProtocolClient(TestCase):
def setUp(self):
@@ -1249,96 +1255,121 @@ class TestTestProtocolClient(TestCase):
"""Test addFailure on a TestProtocolClient."""
self.protocol.addFailure(
self.test, subunit.RemoteError(_u("boo qux")))
- self.assertEqual(
- self.io.getvalue(),
- _b(('failure: %s [\n' + _remote_exception_str + ': boo qux\n]\n')
- % self.test.id()))
+ self.assertThat(self.io.getvalue(), MatchesAny(
+ # testtools < 2.5.0
+ Equals(_b((
+ 'failure: %s [\n' +
+ _remote_exception_str + ': boo qux\n' +
+ ']\n') % self.test.id())),
+ # testtools >= 2.5.0
+ Equals(_b((
+ 'failure: %s [\n' +
+ _remote_exception_repr + ': 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.assertThat([
- _b(("failure: %s [ multipart\n"
- "Content-Type: text/plain\n"
- "something\n"
- "F\r\nserialised\nform0\r\n"
- "Content-Type: text/x-traceback;charset=utf8,language=python\n"
- "traceback\n" + _remote_exception_str_chunked +
- "]\n") % self.test.id()),
- _b(("failure: %s [ multipart\n"
- "Content-Type: text/plain\n"
- "something\n"
- "F\r\nserialised\nform0\r\n"
- "Content-Type: text/x-traceback;language=python,charset=utf8\n"
- "traceback\n" + _remote_exception_str_chunked +
- "]\n") % self.test.id()),
- ],
- Contains(self.io.getvalue())),
+ self.assertThat(self.io.getvalue(), MatchesAny(
+ # testtools < 2.5.0
+ Equals(_b((
+ "failure: %s [ multipart\n"
+ "Content-Type: text/plain\n"
+ "something\n"
+ "F\r\nserialised\nform0\r\n"
+ "Content-Type: text/x-traceback;charset=utf8,language=python\n"
+ "traceback\n" + _remote_exception_str_chunked +
+ "]\n") % self.test.id())),
+ # testtools >= 2.5.0
+ Equals(_b((
+ "failure: %s [ multipart\n"
+ "Content-Type: text/plain\n"
+ "something\n"
+ "F\r\nserialised\nform0\r\n"
+ "Content-Type: text/x-traceback;charset=utf8,language=python\n"
+ "traceback\n" + _remote_exception_repr_chunked +
+ "]\n") % self.test.id()))))
def test_add_error(self):
"""Test stopTest on a TestProtocolClient."""
self.protocol.addError(
self.test, subunit.RemoteError(_u("phwoar crikey")))
- self.assertEqual(
- self.io.getvalue(),
- _b(('error: %s [\n' +
- _remote_exception_str + ": phwoar crikey\n"
- "]\n") % self.test.id()))
+ self.assertThat(self.io.getvalue(), MatchesAny(
+ # testtools < 2.5.0
+ Equals(_b((
+ 'error: %s [\n' +
+ _remote_exception_str + ": phwoar crikey\n"
+ "]\n") % self.test.id())),
+ # testtools >= 2.5.0
+ Equals(_b((
+ 'error: %s [\n' +
+ _remote_exception_repr + ": phwoar crikey\n"
+ "]\n") % self.test.id()))))
def test_add_error_details(self):
"""Test stopTest on a TestProtocolClient with details."""
self.protocol.addError(
self.test, details=self.sample_tb_details)
- self.assertThat([
- _b(("error: %s [ multipart\n"
- "Content-Type: text/plain\n"
- "something\n"
- "F\r\nserialised\nform0\r\n"
- "Content-Type: text/x-traceback;charset=utf8,language=python\n"
- "traceback\n" + _remote_exception_str_chunked +
- "]\n") % self.test.id()),
- _b(("error: %s [ multipart\n"
- "Content-Type: text/plain\n"
- "something\n"
- "F\r\nserialised\nform0\r\n"
- "Content-Type: text/x-traceback;language=python,charset=utf8\n"
- "traceback\n" + _remote_exception_str_chunked +
- "]\n") % self.test.id()),
- ],
- Contains(self.io.getvalue())),
+ self.assertThat(self.io.getvalue(), MatchesAny(
+ # testtools < 2.5.0
+ Equals(_b((
+ "error: %s [ multipart\n"
+ "Content-Type: text/plain\n"
+ "something\n"
+ "F\r\nserialised\nform0\r\n"
+ "Content-Type: text/x-traceback;charset=utf8,language=python\n"
+ "traceback\n" + _remote_exception_str_chunked +
+ "]\n") % self.test.id())),
+ # testtools >= 2.5.0
+ Equals(_b((
+ "error: %s [ multipart\n"
+ "Content-Type: text/plain\n"
+ "something\n"
+ "F\r\nserialised\nform0\r\n"
+ "Content-Type: text/x-traceback;charset=utf8,language=python\n"
+ "traceback\n" + _remote_exception_repr_chunked +
+ "]\n") % self.test.id()))))
def test_add_expected_failure(self):
"""Test addExpectedFailure on a TestProtocolClient."""
self.protocol.addExpectedFailure(
self.test, subunit.RemoteError(_u("phwoar crikey")))
- self.assertEqual(
- self.io.getvalue(),
- _b(('xfail: %s [\n' +
- _remote_exception_str + ": phwoar crikey\n"
- "]\n") % self.test.id()))
+ self.assertThat(self.io.getvalue(), MatchesAny(
+ # testtools < 2.5.0
+ Equals(_b((
+ 'xfail: %s [\n' +
+ _remote_exception_str + ": phwoar crikey\n"
+ "]\n") % self.test.id())),
+ # testtools >= 2.5.0
+ Equals(_b((
+ 'xfail: %s [\n' +
+ _remote_exception_repr + ": phwoar crikey\n"
+ "]\n") % self.test.id()))))
def test_add_expected_failure_details(self):
"""Test addExpectedFailure on a TestProtocolClient with details."""
self.protocol.addExpectedFailure(
self.test, details=self.sample_tb_details)
- self.assertThat([
- _b(("xfail: %s [ multipart\n"
- "Content-Type: text/plain\n"
- "something\n"
- "F\r\nserialised\nform0\r\n"
- "Content-Type: text/x-traceback;charset=utf8,language=python\n"
- "traceback\n" + _remote_exception_str_chunked +
- "]\n") % self.test.id()),
- _b(("xfail: %s [ multipart\n"
- "Content-Type: text/plain\n"
- "something\n"
- "F\r\nserialised\nform0\r\n"
- "Content-Type: text/x-traceback;language=python,charset=utf8\n"
- "traceback\n" + _remote_exception_str_chunked +
- "]\n") % self.test.id()),
- ],
- Contains(self.io.getvalue())),
+ self.assertThat(self.io.getvalue(), MatchesAny(
+ # testtools < 2.5.0
+ Equals(_b((
+ "xfail: %s [ multipart\n"
+ "Content-Type: text/plain\n"
+ "something\n"
+ "F\r\nserialised\nform0\r\n"
+ "Content-Type: text/x-traceback;charset=utf8,language=python\n"
+ "traceback\n" + _remote_exception_str_chunked +
+ "]\n") % self.test.id())),
+ # testtools >= 2.5.0
+ Equals(_b((
+ "xfail: %s [ multipart\n"
+ "Content-Type: text/plain\n"
+ "something\n"
+ "F\r\nserialised\nform0\r\n"
+ "Content-Type: text/x-traceback;charset=utf8,language=python\n"
+ "traceback\n" + _remote_exception_repr_chunked +
+ "]\n") % self.test.id()))))
def test_add_skip(self):
"""Test addSkip on a TestProtocolClient."""