Hello community,
here is the log from the commit of package python-testrepository for
openSUSE:Factory checked in at 2014-09-17 17:26:57
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-testrepository (Old)
and /work/SRC/openSUSE:Factory/.python-testrepository.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-testrepository"
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-testrepository/python-testrepository.changes
2014-02-26 06:55:39.000000000 +0100
+++
/work/SRC/openSUSE:Factory/.python-testrepository.new/python-testrepository.changes
2014-09-17 17:27:26.000000000 +0200
@@ -1,0 +2,32 @@
+Tue Sep 16 06:22:45 UTC 2014 - [email protected]
+
+- update to version 0.0.20:
+ * Tests will be reliably tagged with worker-%d. The previous tagging logic
+ had an implicit race - the tag id was looked up via a closure which gets
+ the state of the pos variable at the position the overall loop has advanced
+ too, not the position when the closure was created.
+ (Robert Collins, #1316858)
+ * Passing --subunit to all testr commands will now consistently output
subunit
+ v2. Previously it would output v1 for stored streams and v2 for live
+ streams. (Robert Collins)
+ * ``run`` was outputting bad MIME types - test/plain, not text/plain.
+ (Robert Collins)
+ * Test filtering was failing under python3 and would only apply the
+ filters to the first test listed by discover. (Clark Boylan, #1317607)
+ * Tests that are enumerated but not executed will no longer reset the test
+ timing data. Enumeration was incorrectly recording a 0 timestamp for
+ enumerated tests. This leads to poor scheduling after an interrupted test
+ run. (Robert Collins, #1322763)
+ * Version 0.0.18 of subunit is now a hard dependency - the v2 protocol solves
+ key issues in concurrency and stream handling. Users that cannot use
subunit
+ v2 can run an older testrepository, or contact upstream to work through
+ whatever issue is blocking them. (Robert Collins)
+ * When list-tests encounters an error, a much clearer response will
+ now be shown. (Robert Collins, #1271133)
+ * The ``get_subunit_stream`` methods now return subunit v2 streams rather
+ than v1 streams, preparing the way for storage of native v2 streams in
+ the repository. (Robert Collins)
+ * ``UI.output_stream`` is now tested for handling of non-utf8 bytestreams.
+ (Robert Collins)
+
+-------------------------------------------------------------------
Old:
----
testrepository-0.0.18.tar.gz
New:
----
testrepository-0.0.20.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-testrepository.spec ++++++
--- /var/tmp/diff_new_pack.EAi3L3/_old 2014-09-17 17:27:27.000000000 +0200
+++ /var/tmp/diff_new_pack.EAi3L3/_new 2014-09-17 17:27:27.000000000 +0200
@@ -17,7 +17,7 @@
Name: python-testrepository
-Version: 0.0.18
+Version: 0.0.20
Release: 0
Summary: A repository of test results
License: BSD-3-Clause or Apache-2.0
++++++ testrepository-0.0.18.tar.gz -> testrepository-0.0.20.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/testrepository-0.0.18/INSTALL.txt
new/testrepository-0.0.20/INSTALL.txt
--- old/testrepository-0.0.18/INSTALL.txt 2011-02-26 08:22:14.000000000
+0100
+++ new/testrepository-0.0.20/INSTALL.txt 2014-08-23 23:38:00.000000000
+0200
@@ -6,7 +6,7 @@
* Python2.4 or newer.
-* subunit
+* subunit (0.0.18 or newer).
* fixtures (https://launchpad.net/python-fixtures, or
http://pypi.python.org/pypi/fixtures/).
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/testrepository-0.0.18/NEWS
new/testrepository-0.0.20/NEWS
--- old/testrepository-0.0.18/NEWS 2013-11-05 00:52:12.000000000 +0100
+++ new/testrepository-0.0.20/NEWS 2014-08-27 01:57:23.000000000 +0200
@@ -5,6 +5,57 @@
NEXT (In development)
+++++++++++++++++++++
+0.0.20
+++++++
+
+IMPROVEMENTS
+------------
+
+* Tests will be reliably tagged with worker-%d. The previous tagging logic
+ had an implicit race - the tag id was looked up via a closure which gets
+ the state of the pos variable at the position the overall loop has advanced
+ too, not the position when the closure was created.
+ (Robert Collins, #1316858)
+
+0.0.19
+++++++
+
+CHANGES
+-------
+
+* Passing --subunit to all testr commands will now consistently output subunit
+ v2. Previously it would output v1 for stored streams and v2 for live
+ streams. (Robert Collins)
+
+* ``run`` was outputting bad MIME types - test/plain, not text/plain.
+ (Robert Collins)
+
+* Test filtering was failing under python3 and would only apply the
+ filters to the first test listed by discover. (Clark Boylan, #1317607)
+
+* Tests that are enumerated but not executed will no longer reset the test
+ timing data. Enumeration was incorrectly recording a 0 timestamp for
+ enumerated tests. This leads to poor scheduling after an interrupted test
+ run. (Robert Collins, #1322763)
+
+* Version 0.0.18 of subunit is now a hard dependency - the v2 protocol solves
+ key issues in concurrency and stream handling. Users that cannot use subunit
+ v2 can run an older testrepository, or contact upstream to work through
+ whatever issue is blocking them. (Robert Collins)
+
+* When list-tests encounters an error, a much clearer response will
+ now be shown. (Robert Collins, #1271133)
+
+INTERNALS
+---------
+
+* The ``get_subunit_stream`` methods now return subunit v2 streams rather
+ than v1 streams, preparing the way for storage of native v2 streams in
+ the repository. (Robert Collins)
+
+* ``UI.output_stream`` is now tested for handling of non-utf8 bytestreams.
+ (Robert Collins)
+
0.0.18
++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/testrepository-0.0.18/PKG-INFO
new/testrepository-0.0.20/PKG-INFO
--- old/testrepository-0.0.18/PKG-INFO 2013-11-05 15:40:31.000000000 +0100
+++ new/testrepository-0.0.20/PKG-INFO 2014-08-27 02:12:15.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: testrepository
-Version: 0.0.18
+Version: 0.0.20
Summary: A repository of test results.
Home-page: https://launchpad.net/testrepository
Author: Robert Collins
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/testrepository-0.0.18/doc/DEVELOPERS.txt
new/testrepository-0.0.20/doc/DEVELOPERS.txt
--- old/testrepository-0.0.18/doc/DEVELOPERS.txt 2013-04-08
12:36:03.000000000 +0200
+++ new/testrepository-0.0.20/doc/DEVELOPERS.txt 2014-08-24
09:43:39.000000000 +0200
@@ -52,3 +52,4 @@
Update NEWS and testrepository/__init__.py version numbers. Release to pypi.
Pivot the next milestone on LP to version, and make a new next milestone.
+Make a new tag and push that to github.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/testrepository-0.0.18/setup.py
new/testrepository-0.0.20/setup.py
--- old/testrepository-0.0.18/setup.py 2013-04-08 12:37:19.000000000 +0200
+++ new/testrepository-0.0.20/setup.py 2014-08-24 00:01:24.000000000 +0200
@@ -95,7 +95,7 @@
],
install_requires=[
'fixtures',
- 'python-subunit >= 0.0.10',
+ 'python-subunit >= 0.0.18',
'testtools >= 0.9.30',
],
extras_require = dict(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/testrepository-0.0.18/testrepository/__init__.py
new/testrepository-0.0.20/testrepository/__init__.py
--- old/testrepository-0.0.18/testrepository/__init__.py 2013-11-05
00:55:48.000000000 +0100
+++ new/testrepository-0.0.20/testrepository/__init__.py 2014-08-27
02:01:54.000000000 +0200
@@ -33,4 +33,4 @@
# 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, 18, 'final', 0)
+__version__ = (0, 0, 20, 'final', 0)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/testrepository-0.0.18/testrepository/commands/load.py
new/testrepository-0.0.20/testrepository/commands/load.py
--- old/testrepository-0.0.18/testrepository/commands/load.py 2013-07-13
13:46:33.000000000 +0200
+++ new/testrepository-0.0.20/testrepository/commands/load.py 2014-08-25
03:42:59.000000000 +0200
@@ -100,6 +100,8 @@
streams = map(opener, self.ui.arguments['streams'])
else:
streams = self.ui.iter_streams('subunit')
+ mktagger = lambda pos, result:testtools.StreamTagger(
+ [result], add=['worker-%d' % pos])
def make_tests():
for pos, stream in enumerate(streams):
if v2_avail:
@@ -121,9 +123,8 @@
case = testtools.DecorateTestCaseResult(case, wrap_result,
methodcaller('startTestRun'),
methodcaller('stopTestRun'))
- case = testtools.DecorateTestCaseResult(case,
- lambda result:testtools.StreamTagger(
- [result], add=['worker-%d' % pos]))
+ decorate = partial(mktagger, pos)
+ case = testtools.DecorateTestCaseResult(case, decorate)
yield (case, str(pos))
case = testtools.ConcurrentStreamTestSuite(make_tests)
# One unmodified copy of the stream to repository storage
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/testrepository-0.0.18/testrepository/commands/run.py
new/testrepository-0.0.20/testrepository/commands/run.py
--- old/testrepository-0.0.18/testrepository/commands/run.py 2013-11-03
20:58:46.000000000 +0100
+++ new/testrepository-0.0.20/testrepository/commands/run.py 2014-03-08
16:19:08.000000000 +0100
@@ -79,7 +79,7 @@
if v2_avail:
stream = subunit.StreamResultToBytes(self.source)
stream.status(test_id='process-returncode', test_status='fail',
- file_name='traceback', mime_type='test/plain;charset=utf8',
+ file_name='traceback', mime_type='text/plain;charset=utf8',
file_bytes=('returncode %d' % returncode).encode('utf8'))
else:
self.source.write(_b('test: process-returncode\n'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/testrepository-0.0.18/testrepository/repository/file.py
new/testrepository-0.0.20/testrepository/repository/file.py
--- old/testrepository-0.0.18/testrepository/repository/file.py 2013-04-01
11:18:36.000000000 +0200
+++ new/testrepository-0.0.20/testrepository/repository/file.py 2014-08-24
12:13:09.000000000 +0200
@@ -25,7 +25,7 @@
import sys
import tempfile
-import subunit
+import subunit.v2
from subunit import TestProtocolClient
import testtools
from testtools.compat import _b
@@ -188,10 +188,23 @@
return self._run_id
def get_subunit_stream(self):
- return BytesIO(self._content)
+ # Transcode - we want V2.
+ v1_stream = BytesIO(self._content)
+ v1_case = subunit.ProtocolTestCase(v1_stream)
+ output = BytesIO()
+ output_stream = subunit.v2.StreamResultToBytes(output)
+ output_stream = testtools.ExtendedToStreamDecorator(output_stream)
+ output_stream.startTestRun()
+ try:
+ v1_case.run(output_stream)
+ finally:
+ output_stream.stopTestRun()
+ output.seek(0)
+ return output
def get_test(self):
- case = subunit.ProtocolTestCase(self.get_subunit_stream())
+ #case = subunit.ProtocolTestCase(self.get_subunit_stream())
+ case = subunit.ProtocolTestCase(BytesIO(self._content))
def wrap_result(result):
# Wrap in a router to mask out startTestRun/stopTestRun from the
# ExtendedToStreamDecorator.
@@ -227,7 +240,7 @@
def _handle_test(self, test_dict):
start, stop = test_dict['timestamps']
- if None in (start, stop):
+ if test_dict['status'] == 'exists' or None in (start, stop):
return
self._times[test_dict['id']] = str(timedelta_to_seconds(stop - start))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/testrepository-0.0.18/testrepository/repository/memory.py
new/testrepository-0.0.20/testrepository/repository/memory.py
--- old/testrepository-0.0.18/testrepository/repository/memory.py
2013-07-17 11:03:54.000000000 +0200
+++ new/testrepository-0.0.20/testrepository/repository/memory.py
2014-08-24 12:13:34.000000000 +0200
@@ -102,8 +102,13 @@
def get_subunit_stream(self):
result = BytesIO()
- serialiser = subunit.TestProtocolClient(result)
- self.run(serialiser)
+ serialiser = subunit.v2.StreamResultToBytes(result)
+ serialiser = testtools.ExtendedToStreamDecorator(serialiser)
+ serialiser.startTestRun()
+ try:
+ self.run(serialiser)
+ finally:
+ serialiser.stopTestRun()
result.seek(0)
return result
@@ -120,7 +125,7 @@
methodcaller('stopTestRun'))
def run(self, result):
- # Speaks original.
+ # Speaks original V1 protocol.
for case in self._repository._failing.values():
case.run(result)
@@ -132,13 +137,12 @@
self._repository = repository
self._partial = partial
self._tests = []
- # Subunit V1 stream for get_subunit_stream
+ # Subunit V2 stream for get_subunit_stream
self._subunit = None
def startTestRun(self):
self._subunit = BytesIO()
- serialiser = subunit.TestProtocolClient(self._subunit)
- serialiser = testtools.StreamToExtendedDecorator(serialiser)
+ serialiser = subunit.v2.StreamResultToBytes(self._subunit)
self._hook = testtools.CopyStreamResult([
testtools.StreamToDict(self._handle_test),
serialiser])
@@ -147,7 +151,7 @@
def _handle_test(self, test_dict):
self._tests.append(test_dict)
start, stop = test_dict['timestamps']
- if None in (start, stop):
+ if test_dict['status'] == 'exists' or None in (start, stop):
return
duration_delta = stop - start
duration_seconds = ((duration_delta.microseconds +
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/testrepository-0.0.18/testrepository/results.py
new/testrepository-0.0.20/testrepository/results.py
--- old/testrepository-0.0.18/testrepository/results.py 2013-07-10
22:28:21.000000000 +0200
+++ new/testrepository-0.0.20/testrepository/results.py 2014-03-08
16:19:08.000000000 +0100
@@ -13,7 +13,11 @@
# limitations under that license.
-from testtools import StreamSummary
+import subunit
+from testtools import (
+ StreamSummary,
+ StreamResult,
+ )
from testrepository.utils import timedelta_to_seconds
@@ -47,3 +51,23 @@
if None in (self._last_time, self._first_time):
return None
return timedelta_to_seconds(self._last_time - self._first_time)
+
+
+#XXX: Should be in testtools.
+class CatFiles(StreamResult):
+ """Cat file attachments received to a stream."""
+
+ def __init__(self, byte_stream):
+ self.stream = subunit.make_stream_binary(byte_stream)
+ self.last_file = None
+
+ def status(self, test_id=None, test_status=None, test_tags=None,
+ runnable=True, file_name=None, file_bytes=None, eof=False,
+ mime_type=None, route_code=None, timestamp=None):
+ if file_name is None:
+ return
+ if self.last_file != file_name:
+ self.stream.write(("--- %s ---\n" % file_name).encode('utf8'))
+ self.last_file = file_name
+ self.stream.write(file_bytes)
+ self.stream.flush()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/testrepository-0.0.18/testrepository/testcommand.py
new/testrepository-0.0.20/testrepository/testcommand.py
--- old/testrepository-0.0.18/testrepository/testcommand.py 2013-07-17
04:50:44.000000000 +0200
+++ new/testrepository-0.0.20/testrepository/testcommand.py 2014-08-23
22:30:39.000000000 +0200
@@ -14,10 +14,14 @@
"""The test command that test repository knows how to run."""
-from extras import try_imports
+from extras import (
+ try_import,
+ try_imports,
+ )
from collections import defaultdict
ConfigParser = try_imports(['ConfigParser', 'configparser'])
+import io
import itertools
import operator
import os.path
@@ -29,7 +33,9 @@
from textwrap import dedent
from fixtures import Fixture
+v2 = try_import('subunit.v2')
+from testrepository import results
from testrepository.testlist import (
parse_enumeration,
write_list,
@@ -273,7 +279,7 @@
"""
if self.test_filters is None:
return test_ids
- filters = map(re.compile, self.test_filters)
+ filters = list(map(re.compile, self.test_filters))
def include(test_id):
for pred in filters:
if pred.search(test_id):
@@ -294,9 +300,16 @@
stdout=subprocess.PIPE, stdin=subprocess.PIPE)
out, err = run_proc.communicate()
if run_proc.returncode != 0:
+ if v2 is not None:
+ new_out = io.BytesIO()
+ v2.ByteStreamToStreamResult(io.BytesIO(out), 'stdout').run(
+ results.CatFiles(new_out))
+ out = new_out.getvalue()
+ self.ui.output_stream(io.BytesIO(out))
+ self.ui.output_stream(io.BytesIO(err))
raise ValueError(
"Non-zero exit code (%d) from test listing."
- " stdout=%r, stderr=%r" % (run_proc.returncode, out, err))
+ % (run_proc.returncode))
ids = parse_enumeration(out)
return ids
finally:
@@ -443,8 +456,8 @@
out, err = run_proc.communicate()
if run_proc.returncode:
raise ValueError(
- "test_run_concurrency failed: exit code %d, stderr=%r" % (
- run_proc.returncode, err))
+ "test_run_concurrency failed: exit code %d, stderr='%s'" % (
+ run_proc.returncode, err.decode('utf8', 'replace')))
return int(out.strip())
def local_concurrency(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/testrepository-0.0.18/testrepository/tests/commands/test_failing.py
new/testrepository-0.0.20/testrepository/tests/commands/test_failing.py
--- old/testrepository-0.0.18/testrepository/tests/commands/test_failing.py
2013-04-11 13:19:07.000000000 +0200
+++ new/testrepository-0.0.20/testrepository/tests/commands/test_failing.py
2014-08-23 23:20:54.000000000 +0200
@@ -15,13 +15,16 @@
"""Tests for the failing command."""
import doctest
+from io import BytesIO
+from subunit.v2 import ByteStreamToStreamResult
import testtools
from testtools.compat import _b
from testtools.matchers import (
DocTestMatches,
Equals,
)
+from testtools.testresult.doubles import StreamResult
from testrepository.commands import failing
from testrepository.ui.model import UI
@@ -78,9 +81,23 @@
self.assertEqual(0, cmd.execute())
self.assertEqual(1, len(ui.outputs))
self.assertEqual('stream', ui.outputs[0][0])
- self.assertThat(ui.outputs[0][1].decode('utf8'),
- DocTestMatches("""...test: ...failing
-...failure: ...failing...""", doctest.ELLIPSIS))
+ as_subunit = BytesIO(ui.outputs[0][1])
+ stream = ByteStreamToStreamResult(as_subunit)
+ log = StreamResult()
+ log.startTestRun()
+ try:
+ stream.run(log)
+ finally:
+ log.stopTestRun()
+ self.assertEqual(
+ log._events, [
+ ('startTestRun',),
+ ('status', 'failing', 'inprogress', None, True, None, None, False,
+ None, None, Wildcard),
+ ('status', 'failing', 'fail', None, True, None, None, False, None,
+ None, Wildcard),
+ ('stopTestRun',)
+ ])
def test_with_subunit_no_failures_exit_0(self):
ui, cmd = self.get_test_ui_and_cmd(options=[('subunit', True)])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/testrepository-0.0.18/testrepository/tests/commands/test_last.py
new/testrepository-0.0.20/testrepository/tests/commands/test_last.py
--- old/testrepository-0.0.18/testrepository/tests/commands/test_last.py
2013-04-11 13:18:22.000000000 +0200
+++ new/testrepository-0.0.20/testrepository/tests/commands/test_last.py
2014-08-23 23:20:54.000000000 +0200
@@ -14,9 +14,12 @@
"""Tests for the last command."""
+from io import BytesIO
+
+from subunit.v2 import ByteStreamToStreamResult
import testtools
-from testtools.compat import _b
from testtools.matchers import Equals
+from testtools.testresult.doubles import StreamResult
from testrepository.commands import last
from testrepository.ui.model import UI
@@ -104,11 +107,20 @@
self.assertEqual([
('stream', Wildcard),
], ui.outputs)
- self.assertThat(ui.outputs[0][1], Equals(_b("""\
-test: failing
-failure: failing [ multipart
-]
-test: ok
-successful: ok [ multipart
-]
-""")))
+ as_subunit = BytesIO(ui.outputs[0][1])
+ stream = ByteStreamToStreamResult(as_subunit)
+ log = StreamResult()
+ log.startTestRun()
+ try:
+ stream.run(log)
+ finally:
+ log.stopTestRun()
+ self.assertEqual(
+ log._events, [
+ ('startTestRun',),
+ ('status', 'failing', 'fail', None, True, None, None, False,
+ None, None, None),
+ ('status', 'ok', 'success', None, True, None, None, False, None,
+ None, None),
+ ('stopTestRun',)
+ ])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/testrepository-0.0.18/testrepository/tests/commands/test_run.py
new/testrepository-0.0.20/testrepository/tests/commands/test_run.py
--- old/testrepository-0.0.18/testrepository/tests/commands/test_run.py
2013-11-03 20:58:46.000000000 +0100
+++ new/testrepository-0.0.20/testrepository/tests/commands/test_run.py
2014-03-08 16:19:08.000000000 +0100
@@ -532,7 +532,7 @@
buffer.write(b'foo\nbar\n')
stream = subunit.StreamResultToBytes(buffer)
stream.status(test_id='process-returncode', test_status='fail',
- file_name='traceback', mime_type='test/plain;charset=utf8',
+ file_name='traceback', mime_type='text/plain;charset=utf8',
file_bytes=b'returncode 1')
expected_content = buffer.getvalue()
else:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/testrepository-0.0.18/testrepository/tests/test_repository.py
new/testrepository-0.0.20/testrepository/tests/test_repository.py
--- old/testrepository-0.0.18/testrepository/tests/test_repository.py
2013-04-01 11:31:50.000000000 +0200
+++ new/testrepository-0.0.20/testrepository/tests/test_repository.py
2014-08-24 12:11:22.000000000 +0200
@@ -20,7 +20,10 @@
)
import doctest
-from subunit import iso8601
+from subunit import (
+ iso8601,
+ v2,
+ )
from testresources import TestResource
from testtools import (
@@ -29,7 +32,10 @@
)
import testtools
from testtools.compat import _b
-from testtools.testresult.doubles import ExtendedTestResult
+from testtools.testresult.doubles import (
+ ExtendedTestResult,
+ StreamResult,
+ )
from testtools.matchers import DocTestMatches, raises
from testrepository import repository
@@ -113,12 +119,18 @@
return clone_test_with_new_id(case, id)
-def run_timed(id, duration, result):
- """Make and run a test taking duration seconds."""
+def run_timed(id, duration, result, enumeration=False):
+ """Make and run a test taking duration seconds.
+
+ :param enumeration: If True, don't run, just enumerate.
+ """
start = datetime.now(tz=iso8601.Utc())
- result.status(test_id=id, test_status='inprogress', timestamp=start)
- result.status(test_id=id, test_status='success',
- timestamp=start + timedelta(seconds=duration))
+ if enumeration:
+ result.status(test_id=id, test_status='exists', timestamp=start)
+ else:
+ result.status(test_id=id, test_status='inprogress', timestamp=start)
+ result.status(test_id=id, test_status='success',
+ timestamp=start + timedelta(seconds=duration))
class TestRepositoryErrors(ResourcedTestCase):
@@ -374,6 +386,61 @@
run = repo.get_failing()
self.assertEqual(None, run.get_id())
+ def test_get_failing_get_subunit_stream(self):
+ repo = self.repo_impl.initialise(self.sample_url)
+ result = repo.get_inserter()
+ legacy_result = testtools.ExtendedToStreamDecorator(result)
+ legacy_result.startTestRun()
+ make_test('testrepository.tests.test_repository.Case.method',
False).run(legacy_result)
+ legacy_result.stopTestRun()
+ run = repo.get_failing()
+ as_subunit = run.get_subunit_stream()
+ stream = v2.ByteStreamToStreamResult(as_subunit)
+ log = StreamResult()
+ log.startTestRun()
+ try:
+ stream.run(log)
+ finally:
+ log.stopTestRun()
+ self.assertEqual(
+ log._events, [
+ ('startTestRun',),
+ ('status',
+ 'testrepository.tests.test_repository.Case.method',
+ 'inprogress',
+ None,
+ True,
+ None,
+ None,
+ False,
+ None,
+ None,
+ Wildcard),
+ ('status',
+ 'testrepository.tests.test_repository.Case.method',
+ None,
+ None,
+ True,
+ 'traceback',
+ Wildcard,
+ True,
+ Wildcard,
+ None,
+ Wildcard),
+ ('status',
+ 'testrepository.tests.test_repository.Case.method',
+ 'fail',
+ None,
+ True,
+ None,
+ None,
+ False,
+ None,
+ None,
+ Wildcard),
+ ('stopTestRun',)
+ ])
+
def test_get_subunit_from_test_run(self):
repo = self.repo_impl.initialise(self.sample_url)
result = repo.get_inserter()
@@ -384,10 +451,41 @@
inserted = result.get_id()
run = repo.get_test_run(inserted)
as_subunit = run.get_subunit_stream()
- self.assertThat(as_subunit.read().decode('utf8'),
- DocTestMatches("""...test:
testrepository.tests.test_repository.Case.method...
-successful: testrepository.tests.test_repository.Case.method...
-""", doctest.ELLIPSIS))
+ stream = v2.ByteStreamToStreamResult(as_subunit)
+ log = StreamResult()
+ log.startTestRun()
+ try:
+ stream.run(log)
+ finally:
+ log.stopTestRun()
+ self.assertEqual(
+ log._events,
+ [
+ ('startTestRun',),
+ ('status',
+ 'testrepository.tests.test_repository.Case.method',
+ 'inprogress',
+ None,
+ True,
+ None,
+ None,
+ False,
+ None,
+ None,
+ Wildcard),
+ ('status',
+ 'testrepository.tests.test_repository.Case.method',
+ 'success',
+ None,
+ True,
+ None,
+ None,
+ False,
+ None,
+ None,
+ Wildcard),
+ ('stopTestRun',)
+ ])
def test_get_test_from_test_run(self):
repo = self.repo_impl.initialise(self.sample_url)
@@ -423,6 +521,22 @@
self.assertEqual({test_name: 0.1},
repo.get_test_times([test_name])['known'])
+ def test_inserted_exists_no_impact_on_test_times(self):
+ repo = self.repo_impl.initialise(self.sample_url)
+ result = repo.get_inserter()
+ legacy_result = testtools.ExtendedToStreamDecorator(result)
+ legacy_result.startTestRun()
+ test_name = 'testrepository.tests.test_repository.Case.method'
+ run_timed(test_name, 0.1, legacy_result)
+ legacy_result.stopTestRun()
+ result = repo.get_inserter()
+ result.startTestRun()
+ test_name = 'testrepository.tests.test_repository.Case.method'
+ run_timed(test_name, 0.2, result, True)
+ result.stopTestRun()
+ self.assertEqual({test_name: 0.1},
+ repo.get_test_times([test_name])['known'])
+
def test_get_test_ids(self):
repo = self.repo_impl.initialise(self.sample_url)
inserter = repo.get_inserter()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/testrepository-0.0.18/testrepository/tests/test_setup.py
new/testrepository-0.0.20/testrepository/tests/test_setup.py
--- old/testrepository-0.0.18/testrepository/tests/test_setup.py
2013-02-06 11:01:04.000000000 +0100
+++ new/testrepository-0.0.20/testrepository/tests/test_setup.py
2014-08-23 23:16:28.000000000 +0200
@@ -35,7 +35,7 @@
proc = subprocess.Popen([sys.executable, path, 'bdist'],
stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT, universal_newlines=True)
- output, _ = proc.communicate()
+ output, err = proc.communicate()
self.assertThat(output, MatchesAny(
# win32
DocTestMatches("""...
@@ -48,4 +48,5 @@
...bin/testr ...
""", doctest.ELLIPSIS)
))
- self.assertEqual(0, proc.returncode)
+ self.assertEqual(0, proc.returncode,
+ "Setup failed out=%r err=%r" % (output, err))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/testrepository-0.0.18/testrepository/tests/test_testcommand.py
new/testrepository-0.0.20/testrepository/tests/test_testcommand.py
--- old/testrepository-0.0.18/testrepository/tests/test_testcommand.py
2013-07-17 04:53:08.000000000 +0200
+++ new/testrepository-0.0.20/testrepository/tests/test_testcommand.py
2014-05-18 20:24:04.000000000 +0200
@@ -575,3 +575,14 @@
fixture = self.useFixture(command.get_run_command(
test_ids=['return', 'of', 'the', 'king'], test_filters=filters))
self.assertEqual(['return'], fixture.test_ids)
+
+ def test_filter_tests_by_regex_supplied_ids_multi_match(self):
+ ui, command = self.get_test_ui_and_cmd()
+ ui.proc_outputs = [_b('returned\nids\n')]
+ self.set_config(
+ '[DEFAULT]\ntest_command=foo $LISTOPT
$IDLIST\ntest_id_list_default=whoo yea\n'
+ 'test_list_option=--list\n')
+ filters = ['return']
+ fixture = self.useFixture(command.get_run_command(
+ test_ids=['return', 'of', 'the', 'king', 'thereisnoreturn'],
test_filters=filters))
+ self.assertEqual(['return', 'thereisnoreturn'], fixture.test_ids)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/testrepository-0.0.18/testrepository/tests/test_ui.py
new/testrepository-0.0.20/testrepository/tests/test_ui.py
--- old/testrepository-0.0.18/testrepository/tests/test_ui.py 2013-04-11
13:13:52.000000000 +0200
+++ new/testrepository-0.0.20/testrepository/tests/test_ui.py 2014-08-24
11:54:08.000000000 +0200
@@ -119,6 +119,11 @@
ui = self.get_test_ui()
ui.output_stream(BytesIO())
+ def test_output_stream_non_utf8(self):
+ # When the stream has non-utf8 bytes it still outputs correctly.
+ ui = self.get_test_ui()
+ ui.output_stream(BytesIO(_b('\xfa')))
+
def test_output_table(self):
# output_table shows a table.
ui = self.get_test_ui()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/testrepository-0.0.18/testrepository/tests/ui/test_cli.py
new/testrepository-0.0.20/testrepository/tests/ui/test_cli.py
--- old/testrepository-0.0.18/testrepository/tests/ui/test_cli.py
2013-07-13 13:55:12.000000000 +0200
+++ new/testrepository-0.0.20/testrepository/tests/ui/test_cli.py
2014-08-23 23:05:41.000000000 +0200
@@ -109,7 +109,8 @@
except Exception:
err_tuple = sys.exc_info()
expected = str(err_tuple[1]) + '\n'
- stdout = StringIO()
+ bytestream = BytesIO()
+ stdout = TextIOWrapper(bytestream, 'utf8', line_buffering=True)
stdin = StringIO()
stderr = StringIO()
ui = cli.UI([], stdin, stdout, stderr)
@@ -128,6 +129,9 @@
<BLANKLINE>
fooo
""")
+ # This should be a BytesIO + Textwrapper, but pdb on 2.7 writes bytes
+ # - this code is the most pragmatic to test on 2.6 and up, and 3.2 and
+ # up.
stdout = StringIO()
stdin = StringIO(_u('c\n'))
stderr = StringIO()
@@ -196,7 +200,8 @@
ui._stdout.buffer.getvalue())
def test_parse_error_goes_to_stderr(self):
- stdout = StringIO()
+ bytestream = BytesIO()
+ stdout = TextIOWrapper(bytestream, 'utf8', line_buffering=True)
stdin = StringIO()
stderr = StringIO()
ui = cli.UI(['one'], stdin, stdout, stderr)
@@ -206,7 +211,8 @@
self.assertEqual("Could not find command 'one'.\n", stderr.getvalue())
def test_parse_excess_goes_to_stderr(self):
- stdout = StringIO()
+ bytestream = BytesIO()
+ stdout = TextIOWrapper(bytestream, 'utf8', line_buffering=True)
stdin = StringIO()
stderr = StringIO()
ui = cli.UI(['one'], stdin, stdout, stderr)
@@ -248,7 +254,8 @@
self.assertEqual(True, ui.options.subunit)
def test_dash_dash_help_shows_help(self):
- stdout = StringIO()
+ bytestream = BytesIO()
+ stdout = TextIOWrapper(bytestream, 'utf8', line_buffering=True)
stdin = StringIO()
stderr = StringIO()
ui = cli.UI(['--help'], stdin, stdout, stderr)
@@ -263,7 +270,7 @@
self.assertThat(exc_info, MatchesException(SystemExit(0)))
else:
self.fail('ui.set_command did not raise')
- self.assertThat(stdout.getvalue(),
+ self.assertThat(bytestream.getvalue().decode('utf8'),
DocTestMatches("""Usage: run.py bar [options] foo
...
A command that can be run...
@@ -352,9 +359,11 @@
def test_initial_stream(self):
# CLITestResult.__init__ does not do anything to the stream it is
# given.
- stream = StringIO()
- cli.CLITestResult(cli.UI(None, None, None, None), stream, lambda: None)
- self.assertEqual('', stream.getvalue())
+ bytestream = BytesIO()
+ stream = TextIOWrapper(bytestream, 'utf8', line_buffering=True)
+ ui = cli.UI(None, None, None, None)
+ cli.CLITestResult(ui, stream, lambda: None)
+ self.assertEqual(_b(''), bytestream.getvalue())
def test_format_error(self):
# CLITestResult formats errors by giving them a big fat line, a title
@@ -376,7 +385,8 @@
def test_addFail_outputs_error(self):
# CLITestResult.status test_status='fail' outputs the given error
# immediately to the stream.
- stream = StringIO()
+ bytestream = BytesIO()
+ stream = TextIOWrapper(bytestream, 'utf8', line_buffering=True)
result = self.make_result(stream)[0]
error = self.make_exc_info()
error_text = 'foo\nbar\n'
@@ -385,7 +395,7 @@
file_name='traceback', mime_type='text/plain;charset=utf8',
file_bytes=error_text.encode('utf8'))
self.assertThat(
- stream.getvalue(),
+ bytestream.getvalue().decode('utf8'),
DocTestMatches(result._format_error('FAIL', self, error_text)))
def test_addFailure_handles_string_encoding(self):
@@ -412,7 +422,8 @@
self.assertEqual(b'', bytestream.getvalue())
def test_make_result_tag_filter(self):
- stream = StringIO()
+ bytestream = BytesIO()
+ stream = TextIOWrapper(bytestream, 'utf8', line_buffering=True)
result, summary = self.make_result(
stream, filter_tags=set(['worker-0']))
# Generate a bunch of results with tags in the same events that
@@ -438,5 +449,5 @@
----------------------------------------------------------------------
Ran 1 tests
FAILED (id=None, failures=1, skips=1)
-""", stream.getvalue())
+""", bytestream.getvalue().decode('utf8'))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/testrepository-0.0.18/testrepository/ui/cli.py
new/testrepository-0.0.20/testrepository/ui/cli.py
--- old/testrepository-0.0.18/testrepository/ui/cli.py 2013-04-13
18:32:47.000000000 +0200
+++ new/testrepository-0.0.20/testrepository/ui/cli.py 2014-08-25
03:43:29.000000000 +0200
@@ -93,6 +93,7 @@
self._stdin = stdin
self._stdout = stdout
self._stderr = stderr
+ self._binary_stdout = None
def _iter_streams(self, stream_type):
# Only the first stream declared in a command can be accepted at the
@@ -155,13 +156,17 @@
self._stdout.write(_u('\n'))
def output_stream(self, stream):
+ if not self._binary_stdout:
+ self._binary_stdout = subunit.make_stream_binary(self._stdout)
contents = stream.read(65536)
assert type(contents) is bytes, \
"Bad stream contents %r" % type(contents)
- # Outputs bytes, treat them as utf8. Probably needs fixing.
+ # If there are unflushed bytes in the text wrapper, we need to sync..
+ self._stdout.flush()
while contents:
- self._stdout.write(contents.decode('utf8'))
+ self._binary_stdout.write(contents)
contents = stream.read(65536)
+ self._binary_stdout.flush()
def output_table(self, table):
# stringify
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/testrepository-0.0.18/testrepository/ui/model.py
new/testrepository-0.0.20/testrepository/ui/model.py
--- old/testrepository-0.0.18/testrepository/ui/model.py 2013-04-11
13:14:26.000000000 +0200
+++ new/testrepository-0.0.20/testrepository/ui/model.py 2014-03-08
16:19:08.000000000 +0100
@@ -33,7 +33,7 @@
def communicate(self):
self.ui.outputs.append(('communicate',))
- return self.stdout.getvalue(), ''
+ return self.stdout.getvalue(), b''
def wait(self):
return self.returncode
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/testrepository-0.0.18/testrepository.egg-info/PKG-INFO
new/testrepository-0.0.20/testrepository.egg-info/PKG-INFO
--- old/testrepository-0.0.18/testrepository.egg-info/PKG-INFO 2013-11-05
15:40:31.000000000 +0100
+++ new/testrepository-0.0.20/testrepository.egg-info/PKG-INFO 2014-08-27
02:12:14.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: testrepository
-Version: 0.0.18
+Version: 0.0.20
Summary: A repository of test results.
Home-page: https://launchpad.net/testrepository
Author: Robert Collins
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/testrepository-0.0.18/testrepository.egg-info/requires.txt
new/testrepository-0.0.20/testrepository.egg-info/requires.txt
--- old/testrepository-0.0.18/testrepository.egg-info/requires.txt
2013-11-05 15:40:31.000000000 +0100
+++ new/testrepository-0.0.20/testrepository.egg-info/requires.txt
2014-08-27 02:12:14.000000000 +0200
@@ -1,5 +1,5 @@
fixtures
-python-subunit >= 0.0.10
+python-subunit >= 0.0.18
testtools >= 0.9.30
[test]
--
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]