subunit: Update to latest upstream version.
authorJelmer Vernooij <jelmer@samba.org>
Wed, 26 Dec 2012 21:11:13 +0000 (22:11 +0100)
committerJelmer Vernooij <jelmer@samba.org>
Thu, 27 Dec 2012 20:08:32 +0000 (21:08 +0100)
Autobuild-User(master): Jelmer Vernooij <jelmer@samba.org>
Autobuild-Date(master): Thu Dec 27 21:08:32 CET 2012 on sn-devel-104

13 files changed:
lib/subunit/INSTALL
lib/subunit/MANIFEST.in
lib/subunit/Makefile.am
lib/subunit/NEWS
lib/subunit/README
lib/subunit/configure.ac
lib/subunit/python/subunit/__init__.py
lib/subunit/python/subunit/run.py
lib/subunit/python/subunit/test_results.py
lib/subunit/python/subunit/tests/test_test_protocol.py
lib/subunit/python/subunit/tests/test_test_results.py
lib/subunit/runtests.py
lib/subunit/setup.py

index 2a053d8ad6db18fa1067dc10354e5e3358d5eddb..eeea734f6a959cc288f847cd7f4847e1df14de21 100644 (file)
@@ -14,7 +14,7 @@ Dependencies
 * Python for the filters
 * 'testtools' (On Debian and Ubuntu systems the 'python-testtools' package,
   the testtools package on pypi, or https://launchpad.net/testtools) for
-  the extended test API which permits attachments. Version 0.9.11 or newer is 
+  the extended test API which permits attachments. Version 0.9.23 or newer is 
   required. Of particular note, http://testtools.python-hosting.com/ is not
   the testtools you want.
 * A C compiler for the C bindings
index 7c449cf7e7fb5044882f74814344a94176488f53..eb989816283f4cab3ee65670a848241158ba71ff 100644 (file)
@@ -16,6 +16,5 @@ exclude missing
 prune perl
 exclude py-compile
 prune shell
-prune python/iso8601
 exclude stamp-h1
 include NEWS
index 310c0426ae500b5a39295672db4703354fbd2a7f..da1602037ed12091719ba26f099e7aa138946f73 100644 (file)
@@ -35,6 +35,7 @@ EXTRA_DIST =  \
        python/subunit/tests/test_test_protocol.py \
        python/subunit/tests/test_test_results.py \
        runtests.py \
+       setup.py \
        shell/README \
        shell/share/subunit.sh \
        shell/subunit-ui.patch \
@@ -48,8 +49,10 @@ include_subunitdir = $(includedir)/subunit
 dist_bin_SCRIPTS = \
        filters/subunit-filter \
        filters/subunit-ls \
+       filters/subunit-notify \
        filters/subunit-stats \
        filters/subunit-tags \
+       filters/subunit2csv \
        filters/subunit2gtk \
        filters/subunit2junitxml \
        filters/subunit2pyunit \
index f28ec5a6df9811b698d255b67bc7b988c4411570..081dc5dbfccf3ca2ffb020edc58a1604562e56aa 100644 (file)
@@ -5,12 +5,25 @@ subunit release notes
 NEXT (In development)
 ---------------------
 
+0.0.9
+-----
+
 BUG FIXES
 ~~~~~~~~~
 
+* All the source files are now included in the distribution tarball.
+  (Arfrever Frehtes Taifersar Arahesis, Robert Collins, #996275)
+
 * ``python/subunit/tests/test_run.py`` and ``python/subunit/filters.py`` were
   not included in the 0.0.8 tarball. (Robert Collins)
 
+* Test ids which include non-ascii unicode characters are now supported.
+  (Robert Collins, #1029866)
+
+* The ``failfast`` option to ``subunit.run`` will now work. The dependency on
+  testtools has been raised to 0.9.23 to permit this.
+  (Robert Collins, #1090582)
+
 0.0.8
 -----
 
index 4818a057bff2c0343f025332e900ec0fa8365b38..103a32cdf9bb4791eb0a60ce0711f47cafb35c24 100644 (file)
@@ -43,6 +43,7 @@ A number of useful things can be done easily with subunit:
 
 Subunit supplies the following filters:
  * tap2subunit - convert perl's TestAnythingProtocol to subunit.
+ * subunit2csv - convert a subunit stream to csv.
  * subunit2pyunit - convert a subunit stream to pyunit test results.
  * subunit2gtk - show a subunit stream in GTK.
  * subunit2junitxml - convert a subunit stream to JUnit's XML format.
@@ -214,3 +215,15 @@ to indicate a test that errored in some expected fashion (also know as "TODO"
 tests in some frameworks). uxsuccess is used to indicate and unexpected success
 where a test though to be failing actually passes. It is complementary to
 xfail.
+
+Hacking on subunit
+------------------
+
+Releases
+========
+
+* Update versions in configure.ac and python/subunit/__init__.py.
+* Make PyPI and regular tarball releases. Upload the regular one to LP, the
+  PyPI one to PyPI.
+* Push a tagged commit.
+
index 223b3c9b4997b2e0fdbb0c0459066ee550c210bc..cf21d554808bad1432979e411ea440a1d2e4ac9d 100644 (file)
@@ -1,6 +1,6 @@
 m4_define([SUBUNIT_MAJOR_VERSION], [0])
 m4_define([SUBUNIT_MINOR_VERSION], [0])
-m4_define([SUBUNIT_MICRO_VERSION], [8])
+m4_define([SUBUNIT_MICRO_VERSION], [9])
 m4_define([SUBUNIT_VERSION],
 m4_defn([SUBUNIT_MAJOR_VERSION]).m4_defn([SUBUNIT_MINOR_VERSION]).m4_defn([SUBUNIT_MICRO_VERSION]))
 AC_PREREQ([2.59])
index 6015c0e68ca050237178c42efa0b8094668091ea..42dcf297e4baeaa124761bbcdd8f820d35aace71 100644 (file)
@@ -147,6 +147,19 @@ from testtools import testresult
 
 from subunit import chunked, details, iso8601, test_results
 
+# same format as sys.version_info: "A tuple containing the five components of
+# the version number: major, minor, micro, releaselevel, and serial. All
+# values except releaselevel are integers; the release level is 'alpha',
+# 'beta', 'candidate', or 'final'. The version_info value corresponding to the
+# Python version 2.0 is (2, 0, 0, 'final', 0)."  Additionally we use a
+# releaselevel of 'dev' for unreleased under-development code.
+#
+# If the releaselevel is 'alpha' then the major/minor/micro components are not
+# established at this point, and setup.py will use a version of next-$(revno).
+# If the releaselevel is 'final', then the tarball will be major.minor.micro.
+# Otherwise it is major.minor.micro~$(revno).
+
+__version__ = (0, 0, 9, 'final', 0)
 
 PROGRESS_SET = 0
 PROGRESS_CUR = 1
@@ -636,6 +649,8 @@ class TestProtocolClient(testresult.TestResult):
             to subunit.Content objects.
         """
         self._addOutcome("error", test, error=error, details=details)
+        if self.failfast:
+            self.stop()
 
     def addExpectedFailure(self, test, error=None, details=None):
         """Report an expected failure in test test.
@@ -666,6 +681,8 @@ class TestProtocolClient(testresult.TestResult):
             to subunit.Content objects.
         """
         self._addOutcome("failure", test, error=error, details=details)
+        if self.failfast:
+            self.stop()
 
     def _addOutcome(self, outcome, test, error=None, details=None,
         error_permitted=True):
@@ -685,7 +702,7 @@ class TestProtocolClient(testresult.TestResult):
         :param error_permitted: If True then one and only one of error or
             details must be supplied. If False then error must not be supplied
             and details is still optional.  """
-        self._stream.write(_b("%s: %s" % (outcome, test.id())))
+        self._stream.write(_b("%s: " % outcome) + self._test_id(test))
         if error_permitted:
             if error is None and details is None:
                 raise ValueError
@@ -730,11 +747,19 @@ class TestProtocolClient(testresult.TestResult):
         """
         self._addOutcome("uxsuccess", test, details=details,
             error_permitted=False)
+        if self.failfast:
+            self.stop()
+
+    def _test_id(self, test):
+        result = test.id()
+        if type(result) is not bytes:
+            result = result.encode('utf8')
+        return result
 
     def startTest(self, test):
         """Mark a test as starting its test run."""
         super(TestProtocolClient, self).startTest(test)
-        self._stream.write(_b("test: %s\n" % test.id()))
+        self._stream.write(_b("test: ") + self._test_id(test) + _b("\n"))
         self._stream.flush()
 
     def stopTest(self, test):
index ca5fe5c17e0e4ac1506de39a3bae2a1fffe9af88..b5ccea449d1ff11059276396515ba5dd148def9e 100755 (executable)
@@ -34,13 +34,22 @@ from testtools.run import (
 
 
 class SubunitTestRunner(object):
-    def __init__(self, stream=sys.stdout):
-        self.stream = stream
+    def __init__(self, verbosity=None, failfast=None, buffer=None, stream=None):
+        """Create a TestToolsTestRunner.
+
+        :param verbosity: Ignored.
+        :param failfast: Stop running tests at the first failure.
+        :param buffer: Ignored.
+        """
+        self.failfast = failfast
+        self.stream = stream or sys.stdout
 
     def run(self, test):
         "Run the given test case or test suite."
         result = TestProtocolClient(self.stream)
         result = AutoTimingTestResultDecorator(result)
+        if self.failfast is not None:
+            result.failfast = self.failfast
         test(result)
         return result
 
@@ -70,6 +79,6 @@ class SubunitTestProgram(TestProgram):
 
 if __name__ == '__main__':
     stream = get_default_formatter()
-    runner = SubunitTestRunner(stream)
+    runner = SubunitTestRunner
     SubunitTestProgram(module=None, argv=sys.argv, testRunner=runner,
         stdout=sys.stdout)
index c00a2d3e9706cf3c2011b1c35856e63ff08402b7..91c9bbdc1e4219e21957bd39e16a6c0e06043925 100644 (file)
@@ -78,6 +78,13 @@ class TestResultDecorator(object):
     def addUnexpectedSuccess(self, test, details=None):
         return self.decorated.addUnexpectedSuccess(test, details=details)
 
+    def _get_failfast(self):
+        return getattr(self.decorated, 'failfast', False)
+
+    def _set_failfast(self, value):
+        self.decorated.failfast = value
+    failfast = property(_get_failfast, _set_failfast)
+
     def progress(self, offset, whence):
         return self.decorated.progress(offset, whence)
 
index ec6830d03b82333d6a0ac4af9a068e21368d4410..7831ba16cdfd75e7ca164cb999cb19ab6e00d661 100644 (file)
@@ -18,7 +18,7 @@ import datetime
 import unittest
 import os
 
-from testtools import skipIf, TestCase, TestResult
+from testtools import PlaceHolder, skipIf, TestCase, TestResult
 from testtools.compat import _b, _u, BytesIO
 from testtools.content import Content, TracebackContent, text_content
 from testtools.content_type import ContentType
@@ -1133,6 +1133,7 @@ class TestTestProtocolClient(unittest.TestCase):
     def setUp(self):
         self.io = BytesIO()
         self.protocol = subunit.TestProtocolClient(self.io)
+        self.unicode_test = PlaceHolder(_u('\u2603'))
         self.test = TestTestProtocolClient("test_start_test")
         self.sample_details = {'something':Content(
             ContentType('text', 'plain'), lambda:[_b('serialised\nform')])}
@@ -1145,6 +1146,12 @@ class TestTestProtocolClient(unittest.TestCase):
         self.protocol.startTest(self.test)
         self.assertEqual(self.io.getvalue(), _b("test: %s\n" % self.test.id()))
 
+    def test_start_test_unicode_id(self):
+        """Test startTest on a TestProtocolClient."""
+        self.protocol.startTest(self.unicode_test)
+        expected = _b("test: ") + _u('\u2603').encode('utf8') + _b("\n")
+        self.assertEqual(expected, self.io.getvalue())
+
     def test_stop_test(self):
         # stopTest doesn't output anything.
         self.protocol.stopTest(self.test)
@@ -1156,6 +1163,12 @@ class TestTestProtocolClient(unittest.TestCase):
         self.assertEqual(
             self.io.getvalue(), _b("successful: %s\n" % self.test.id()))
 
+    def test_add_outcome_unicode_id(self):
+        """Test addSuccess on a TestProtocolClient."""
+        self.protocol.addSuccess(self.unicode_test)
+        expected = _b("successful: ") + _u('\u2603').encode('utf8') + _b("\n")
+        self.assertEqual(expected, self.io.getvalue())
+
     def test_add_success_details(self):
         """Test addSuccess on a TestProtocolClient with details."""
         self.protocol.addSuccess(self.test, details=self.sample_details)
index 236dfa22e51f0b15474ff5aae236b7feef86c48a..ff74b9a818f64681c6fa24e4b6480a4b456ceeb6 100644 (file)
@@ -61,6 +61,7 @@ class TimeCapturingResult(unittest.TestResult):
     def __init__(self):
         super(TimeCapturingResult, self).__init__()
         self._calls = []
+        self.failfast = False
 
     def time(self, a_datetime):
         self._calls.append(a_datetime)
@@ -198,6 +199,11 @@ class TestAutoTimingTestResultDecorator(unittest.TestCase):
         self.assertEqual(3, len(self.decorated._calls))
         self.assertNotEqual(None, self.decorated._calls[2])
 
+    def test_set_failfast_True(self):
+        self.assertFalse(self.decorated.failfast)
+        self.result.failfast = True
+        self.assertTrue(self.decorated.failfast)
+
 
 class TestTagCollapsingDecorator(TestCase):
 
index 691e3b34da81ac240cc544a7bd17ad9563212e91..8ecc6cd3fb4c47f1d4237bf8a8392cb6d08bba62 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/env python
 # -*- Mode: python -*-
 #
 # Copyright (C) 2004 Canonical.com
index a78eb999d7cf5262b125d26532a721ca5933e7fa..1a0b192b1b64607bdbc86a95ff43565579c7b3ec 100755 (executable)
@@ -9,7 +9,7 @@ except ImportError:
 else:
     extra = {
         'install_requires': [
-            'testtools>=0.9.11',
+            'testtools>=0.9.23',
         ]
     }
 
@@ -38,6 +38,7 @@ setup(
     long_description=open('README').read(),
     classifiers=[
         'Intended Audience :: Developers',
+        'Programming Language :: Python :: 3',
         'Programming Language :: Python',
         'Topic :: Software Development :: Testing',
     ],
@@ -45,7 +46,7 @@ setup(
     author='Robert Collins',
     author_email='subunit-dev@lists.launchpad.net',
     url='http://launchpad.net/subunit',
-    packages=['subunit'],
+    packages=['subunit', 'subunit.tests'],
     package_dir={'subunit': 'python/subunit'},
     scripts = [
         'filters/subunit2gtk',