Skip to content

Commit 6c0f807

Browse files
committed
Move to subunit v2 for output of stored streams.
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.
1 parent 677ca89 commit 6c0f807

File tree

6 files changed

+173
-27
lines changed

6 files changed

+173
-27
lines changed

NEWS

+8
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ NEXT (In development)
88
CHANGES
99
-------
1010

11+
* Passing --subunit to all testr commands will now consistently output subunit
12+
v2. Previously it would output v1 for stored streams and v2 for live
13+
streams. (Robert Collins)
14+
1115
* ``run`` was outputting bad MIME types - test/plain, not text/plain.
1216
(Robert Collins)
1317

@@ -20,6 +24,10 @@ CHANGES
2024
INTERNALS
2125
---------
2226

27+
* The ``get_subunit_stream`` methods now return subunit v2 streams rather
28+
than v1 streams, preparing the way for storage of native v2 streams in
29+
the repository. (Robert Collins)
30+
2331
* ``UI.output_stream`` is now tested for handling of non-utf8 bytestreams.
2432
(Robert Collins)
2533

testrepository/repository/file.py

+16-3
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
import sys
2626
import tempfile
2727

28-
import subunit
28+
import subunit.v2
2929
from subunit import TestProtocolClient
3030
import testtools
3131
from testtools.compat import _b
@@ -188,10 +188,23 @@ def get_id(self):
188188
return self._run_id
189189

190190
def get_subunit_stream(self):
191-
return BytesIO(self._content)
191+
# Transcode - we want V2.
192+
v1_stream = BytesIO(self._content)
193+
v1_case = subunit.ProtocolTestCase(v1_stream)
194+
output = BytesIO()
195+
output_stream = subunit.v2.StreamResultToBytes(output)
196+
output_stream = testtools.ExtendedToStreamDecorator(output_stream)
197+
output_stream.startTestRun()
198+
try:
199+
v1_case.run(output_stream)
200+
finally:
201+
output_stream.stopTestRun()
202+
output.seek(0)
203+
return output
192204

193205
def get_test(self):
194-
case = subunit.ProtocolTestCase(self.get_subunit_stream())
206+
#case = subunit.ProtocolTestCase(self.get_subunit_stream())
207+
case = subunit.ProtocolTestCase(BytesIO(self._content))
195208
def wrap_result(result):
196209
# Wrap in a router to mask out startTestRun/stopTestRun from the
197210
# ExtendedToStreamDecorator.

testrepository/repository/memory.py

+10-6
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,13 @@ def get_id(self):
102102

103103
def get_subunit_stream(self):
104104
result = BytesIO()
105-
serialiser = subunit.TestProtocolClient(result)
106-
self.run(serialiser)
105+
serialiser = subunit.v2.StreamResultToBytes(result)
106+
serialiser = testtools.ExtendedToStreamDecorator(serialiser)
107+
serialiser.startTestRun()
108+
try:
109+
self.run(serialiser)
110+
finally:
111+
serialiser.stopTestRun()
107112
result.seek(0)
108113
return result
109114

@@ -120,7 +125,7 @@ def wrap_result(result):
120125
methodcaller('stopTestRun'))
121126

122127
def run(self, result):
123-
# Speaks original.
128+
# Speaks original V1 protocol.
124129
for case in self._repository._failing.values():
125130
case.run(result)
126131

@@ -132,13 +137,12 @@ def __init__(self, repository, partial):
132137
self._repository = repository
133138
self._partial = partial
134139
self._tests = []
135-
# Subunit V1 stream for get_subunit_stream
140+
# Subunit V2 stream for get_subunit_stream
136141
self._subunit = None
137142

138143
def startTestRun(self):
139144
self._subunit = BytesIO()
140-
serialiser = subunit.TestProtocolClient(self._subunit)
141-
serialiser = testtools.StreamToExtendedDecorator(serialiser)
145+
serialiser = subunit.v2.StreamResultToBytes(self._subunit)
142146
self._hook = testtools.CopyStreamResult([
143147
testtools.StreamToDict(self._handle_test),
144148
serialiser])

testrepository/tests/commands/test_failing.py

+20-3
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,16 @@
1515
"""Tests for the failing command."""
1616

1717
import doctest
18+
from io import BytesIO
1819

20+
from subunit.v2 import ByteStreamToStreamResult
1921
import testtools
2022
from testtools.compat import _b
2123
from testtools.matchers import (
2224
DocTestMatches,
2325
Equals,
2426
)
27+
from testtools.testresult.doubles import StreamResult
2528

2629
from testrepository.commands import failing
2730
from testrepository.ui.model import UI
@@ -78,9 +81,23 @@ def test_with_subunit_shows_subunit_stream(self):
7881
self.assertEqual(0, cmd.execute())
7982
self.assertEqual(1, len(ui.outputs))
8083
self.assertEqual('stream', ui.outputs[0][0])
81-
self.assertThat(ui.outputs[0][1].decode('utf8'),
82-
DocTestMatches("""...test: ...failing
83-
...failure: ...failing...""", doctest.ELLIPSIS))
84+
as_subunit = BytesIO(ui.outputs[0][1])
85+
stream = ByteStreamToStreamResult(as_subunit)
86+
log = StreamResult()
87+
log.startTestRun()
88+
try:
89+
stream.run(log)
90+
finally:
91+
log.stopTestRun()
92+
self.assertEqual(
93+
log._events, [
94+
('startTestRun',),
95+
('status', 'failing', 'inprogress', None, True, None, None, False,
96+
None, None, Wildcard),
97+
('status', 'failing', 'fail', None, True, None, None, False, None,
98+
None, Wildcard),
99+
('stopTestRun',)
100+
])
84101

85102
def test_with_subunit_no_failures_exit_0(self):
86103
ui, cmd = self.get_test_ui_and_cmd(options=[('subunit', True)])

testrepository/tests/commands/test_last.py

+21-9
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,12 @@
1414

1515
"""Tests for the last command."""
1616

17+
from io import BytesIO
18+
19+
from subunit.v2 import ByteStreamToStreamResult
1720
import testtools
18-
from testtools.compat import _b
1921
from testtools.matchers import Equals
22+
from testtools.testresult.doubles import StreamResult
2023

2124
from testrepository.commands import last
2225
from testrepository.ui.model import UI
@@ -104,11 +107,20 @@ def test_shows_subunit_stream(self):
104107
self.assertEqual([
105108
('stream', Wildcard),
106109
], ui.outputs)
107-
self.assertThat(ui.outputs[0][1], Equals(_b("""\
108-
test: failing
109-
failure: failing [ multipart
110-
]
111-
test: ok
112-
successful: ok [ multipart
113-
]
114-
""")))
110+
as_subunit = BytesIO(ui.outputs[0][1])
111+
stream = ByteStreamToStreamResult(as_subunit)
112+
log = StreamResult()
113+
log.startTestRun()
114+
try:
115+
stream.run(log)
116+
finally:
117+
log.stopTestRun()
118+
self.assertEqual(
119+
log._events, [
120+
('startTestRun',),
121+
('status', 'failing', 'fail', None, True, None, None, False,
122+
None, None, None),
123+
('status', 'ok', 'success', None, True, None, None, False, None,
124+
None, None),
125+
('stopTestRun',)
126+
])

testrepository/tests/test_repository.py

+98-6
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@
2020
)
2121
import doctest
2222

23-
from subunit import iso8601
23+
from subunit import (
24+
iso8601,
25+
v2,
26+
)
2427

2528
from testresources import TestResource
2629
from testtools import (
@@ -29,7 +32,10 @@
2932
)
3033
import testtools
3134
from testtools.compat import _b
32-
from testtools.testresult.doubles import ExtendedTestResult
35+
from testtools.testresult.doubles import (
36+
ExtendedTestResult,
37+
StreamResult,
38+
)
3339
from testtools.matchers import DocTestMatches, raises
3440

3541
from testrepository import repository
@@ -374,6 +380,61 @@ def test_get_failing_get_id(self):
374380
run = repo.get_failing()
375381
self.assertEqual(None, run.get_id())
376382

383+
def test_get_failing_get_subunit_stream(self):
384+
repo = self.repo_impl.initialise(self.sample_url)
385+
result = repo.get_inserter()
386+
legacy_result = testtools.ExtendedToStreamDecorator(result)
387+
legacy_result.startTestRun()
388+
make_test('testrepository.tests.test_repository.Case.method', False).run(legacy_result)
389+
legacy_result.stopTestRun()
390+
run = repo.get_failing()
391+
as_subunit = run.get_subunit_stream()
392+
stream = v2.ByteStreamToStreamResult(as_subunit)
393+
log = StreamResult()
394+
log.startTestRun()
395+
try:
396+
stream.run(log)
397+
finally:
398+
log.stopTestRun()
399+
self.assertEqual(
400+
log._events, [
401+
('startTestRun',),
402+
('status',
403+
'testrepository.tests.test_repository.Case.method',
404+
'inprogress',
405+
None,
406+
True,
407+
None,
408+
None,
409+
False,
410+
None,
411+
None,
412+
Wildcard),
413+
('status',
414+
'testrepository.tests.test_repository.Case.method',
415+
None,
416+
None,
417+
True,
418+
'traceback',
419+
Wildcard,
420+
True,
421+
Wildcard,
422+
None,
423+
Wildcard),
424+
('status',
425+
'testrepository.tests.test_repository.Case.method',
426+
'fail',
427+
None,
428+
True,
429+
None,
430+
None,
431+
False,
432+
None,
433+
None,
434+
Wildcard),
435+
('stopTestRun',)
436+
])
437+
377438
def test_get_subunit_from_test_run(self):
378439
repo = self.repo_impl.initialise(self.sample_url)
379440
result = repo.get_inserter()
@@ -384,10 +445,41 @@ def test_get_subunit_from_test_run(self):
384445
inserted = result.get_id()
385446
run = repo.get_test_run(inserted)
386447
as_subunit = run.get_subunit_stream()
387-
self.assertThat(as_subunit.read().decode('utf8'),
388-
DocTestMatches("""...test: testrepository.tests.test_repository.Case.method...
389-
successful: testrepository.tests.test_repository.Case.method...
390-
""", doctest.ELLIPSIS))
448+
stream = v2.ByteStreamToStreamResult(as_subunit)
449+
log = StreamResult()
450+
log.startTestRun()
451+
try:
452+
stream.run(log)
453+
finally:
454+
log.stopTestRun()
455+
self.assertEqual(
456+
log._events,
457+
[
458+
('startTestRun',),
459+
('status',
460+
'testrepository.tests.test_repository.Case.method',
461+
'inprogress',
462+
None,
463+
True,
464+
None,
465+
None,
466+
False,
467+
None,
468+
None,
469+
Wildcard),
470+
('status',
471+
'testrepository.tests.test_repository.Case.method',
472+
'success',
473+
None,
474+
True,
475+
None,
476+
None,
477+
False,
478+
None,
479+
None,
480+
Wildcard),
481+
('stopTestRun',)
482+
])
391483

392484
def test_get_test_from_test_run(self):
393485
repo = self.repo_impl.initialise(self.sample_url)

0 commit comments

Comments
 (0)