def test_non_subunit_disabled_raises(self): source = BytesIO(b"foo\nbar\n") result = doubles.StreamResult() case = v2.ByteStreamToStreamResult(source) e = self.assertRaises(Exception, case.run, result) # noqa self.assertEqual(b'f', e.args[1]) self.assertEqual(b'oo\nbar\n', source.read()) self.assertEqual([], result._events)
def test_trivial_enumeration(self): source = BytesIO(CONSTANT_ENUM) result = doubles.StreamResult() v2.ByteStreamToStreamResult(source, non_subunit_name="stdout").run(result) self.assertEqual(b'', source.read()) self.assertEqual([ ('status', 'foo', 'exists', None, True, None, None, False, None, None, None), ], result._events)
def check_events(self, source_bytes, events): source = BytesIO(source_bytes) result = doubles.StreamResult() v2.ByteStreamToStreamResult(source, non_subunit_name="stdout").run(result) self.assertEqual(b'', source.read()) self.assertEqual(events, result._events) # any file attachments should be byte contents [as users assume that]. for event in result._events: if event[5] is not None: self.assertIsInstance(event[6], bytes)
def test_includes_timing_output(self): bytestream = io.BytesIO() runner = run.SubunitTestRunner(stream=bytestream) test = testtools.PlaceHolder('name') runner.run(test) bytestream.seek(0) eventstream = StreamResult() v2.ByteStreamToStreamResult(bytestream).run(eventstream) timestamps = [ event[-1] for event in eventstream._events if event is not None ] self.assertNotEqual([], timestamps)
def test_default(self): byte_stream = compat.BytesIO() stream = v2.StreamResultToBytes(byte_stream) stream.status(test_id="foo", test_status="inprogress") stream.status(test_id="foo", test_status="skip") output = self.run_command([], byte_stream.getvalue()) events = doubles.StreamResult() v2.ByteStreamToStreamResult(compat.BytesIO(output)).run(events) self.assertEqual([ ('status', 'foo', 'inprogress'), ('status', 'foo', 'skip'), ], [event[:3] for event in events._events])
def test_enumerates_tests_before_run(self): bytestream = io.BytesIO() runner = run.SubunitTestRunner(stream=bytestream) test1 = testtools.PlaceHolder('name1') test2 = testtools.PlaceHolder('name2') case = unittest.TestSuite([test1, test2]) runner.run(case) bytestream.seek(0) eventstream = StreamResult() v2.ByteStreamToStreamResult(bytestream).run(eventstream) self.assertEqual([ ('status', 'name1', 'exists'), ('status', 'name2', 'exists'), ], [event[:3] for event in eventstream._events[:2]])
def test_signature_middle_utf8_char(self): utf8_bytes = b'\xe3\xb3\x8a' source = BytesIO(utf8_bytes) # Should be treated as one character (it is u'\u3cca') and wrapped result = doubles.StreamResult() v2.ByteStreamToStreamResult(source, non_subunit_name="stdout").run(result) self.assertEqual([ ('status', None, None, None, True, 'stdout', b'\xe3', False, None, None, None), ('status', None, None, None, True, 'stdout', b'\xb3', False, None, None, None), ('status', None, None, None, True, 'stdout', b'\x8a', False, None, None, None), ], result._events)
def test_todo_and_skip(self): # A file # not ok 1 - a fail # not ok 2 - another fail # SKIP instead # results in two tests, numbered and commented. self.tap.write(compat._u("not ok 1 - a fail but # TODO but is TODO\n")) self.tap.write(compat._u("not ok 2 - another fail # SKIP instead\n")) self.tap.seek(0) result = pysubunit.TAP2SubUnit(self.tap, self.subunit) self.assertEqual(0, result) self.subunit.seek(0) events = doubles.StreamResult() v2.ByteStreamToStreamResult(self.subunit).run(events) self.check_events([('status', 'test 1 - a fail but', 'xfail', None, False, 'tap comment', b'but is TODO', True, 'text/plain; charset=UTF8', None, None), ('status', 'test 2 - another fail', 'skip', None, False, 'tap comment', b'instead', True, 'text/plain; charset=UTF8', None, None)])
def tag_stream(original, filtered, tags): """Alter tags on a stream. :param original: The input stream. :param filtered: The output stream. :param tags: The tags to apply. As in a normal stream - a list of 'TAG' or '-TAG' commands. A 'TAG' command will add the tag to the output stream, and override any existing '-TAG' command in that stream. Specifically: * A global 'tags: TAG' will be added to the start of the stream. * Any tags commands with -TAG will have the -TAG removed. A '-TAG' command will remove the TAG command from the stream. Specifically: * A 'tags: -TAG' command will be added to the start of the stream. * Any 'tags: TAG' command will have 'TAG' removed from it. Additionally, any redundant tagging commands (adding a tag globally present, or removing a tag globally removed) are stripped as a by-product of the filtering. :return: 0 """ new_tags, gone_tags = tags_to_new_gone(tags) source = v2.ByteStreamToStreamResult(original, non_subunit_name='stdout') class Tagger(testtools.CopyStreamResult): def status(self, **kwargs): tags = kwargs.get('test_tags') if not tags: tags = set() tags.update(new_tags) tags.difference_update(gone_tags) if tags: kwargs['test_tags'] = tags else: kwargs['test_tags'] = None super(Tagger, self).status(**kwargs) output = Tagger([v2.StreamResultToBytes(filtered)]) source.run(output) return 0
def test_tags(self): byte_stream = compat.BytesIO() stream = v2.StreamResultToBytes(byte_stream) stream.status(test_id="foo", test_status="inprogress", test_tags=set(["a"])) stream.status(test_id="foo", test_status="success", test_tags=set(["a"])) stream.status(test_id="bar", test_status="inprogress") stream.status(test_id="bar", test_status="inprogress") stream.status(test_id="baz", test_status="inprogress", test_tags=set(["a"])) stream.status(test_id="baz", test_status="success", test_tags=set(["a"])) output = self.run_command(['-s', '--with-tag', 'a'], byte_stream.getvalue()) events = doubles.StreamResult() v2.ByteStreamToStreamResult(compat.BytesIO(output)).run(events) ids = set(event[1] for event in events._events) self.assertEqual(set(['foo', 'baz']), ids)
def test_non_pysubunit_encapsulated(self): source = BytesIO(b"foo\nbar\n") result = doubles.StreamResult() v2.ByteStreamToStreamResult(source, non_subunit_name="stdout").run(result) self.assertEqual([ ('status', None, None, None, True, 'stdout', b'f', False, None, None, None), ('status', None, None, None, True, 'stdout', b'o', False, None, None, None), ('status', None, None, None, True, 'stdout', b'o', False, None, None, None), ('status', None, None, None, True, 'stdout', b'\n', False, None, None, None), ('status', None, None, None, True, 'stdout', b'b', False, None, None, None), ('status', None, None, None, True, 'stdout', b'a', False, None, None, None), ('status', None, None, None, True, 'stdout', b'r', False, None, None, None), ('status', None, None, None, True, 'stdout', b'\n', False, None, None, None), ], result._events) self.assertEqual(b'', source.read())
def check_events(self, events): self.subunit.seek(0) eventstream = doubles.StreamResult() v2.ByteStreamToStreamResult(self.subunit).run(eventstream) self.assertEqual(events, eventstream._events)
def run_tests_from_stream(input_stream, result, passthrough_stream=None, forward_stream=None, protocol_version=1, passthrough_subunit=True): """Run tests from a subunit input stream through 'result'. Non-test events - top level file attachments - are expected to be dropped by v2 StreamResults at the present time (as all the analysis code is in ExtendedTestResult API's), so to implement passthrough_stream they are diverted and copied directly when that is set. :param input_stream: A stream containing subunit input. :param result: A TestResult that will receive the test events. NB: This should be an ExtendedTestResult for v1 and a StreamResult for v2. :param passthrough_stream: All non-subunit input received will be sent to this stream. If not provided, uses the ``TestProtocolServer`` default, which is ``sys.stdout``. :param forward_stream: All subunit input received will be forwarded to this stream. If not provided, uses the ``TestProtocolServer`` default, which is to not forward any input. Do not set this when transforming the stream - items would be double-reported. :param protocol_version: What version of the subunit protocol to expect. :param passthrough_subunit: If True, passthrough should be as subunit otherwise unwrap it. Only has effect when forward_stream is None. (when forwarding as subunit non-subunit input is always turned into subunit) """ if 1 == protocol_version: test = pysubunit.ProtocolTestCase(input_stream, passthrough=passthrough_stream, forward=forward_stream) elif 2 == protocol_version: # In all cases we encapsulate unknown inputs. if forward_stream is not None: # Send events to forward_stream as subunit. forward_result = v2.StreamResultToBytes(forward_stream) # If we're passing non-subunit through, copy: if passthrough_stream is None: # Not passing non-test events - split them off to nothing. router = testtools.StreamResultRouter(forward_result) router.add_rule(testtools.StreamResult(), 'test_id', test_id=None) result = testtools.CopyStreamResult([router, result]) else: # otherwise, copy all events to forward_result result = testtools.CopyStreamResult([forward_result, result]) elif passthrough_stream is not None: # Route non-test events to passthrough_stream, unwrapping them for # display. if not passthrough_subunit: passthrough_result = test_results.CatFiles(passthrough_stream) else: passthrough_result = v2.StreamResultToBytes(passthrough_stream) result = testtools.StreamResultRouter(result) result.add_rule(passthrough_result, 'test_id', test_id=None) test = v2.ByteStreamToStreamResult(input_stream, non_subunit_name='stdout') else: raise Exception("Unknown protocol version.") result.startTestRun() test.run(result) result.stopTestRun()
def test_hypothesis_decoding(self, code_bytes): source = BytesIO(code_bytes) result = doubles.StreamResult() stream = v2.ByteStreamToStreamResult(source, non_subunit_name="stdout") stream.run(result) self.assertEqual(b'', source.read())