def xfail_quoted_bracket(self, keyword, as_success): # This tests it is accepted, but cannot test it is used today, because # of not having a way to expose it in Python so far. self.protocol.lineReceived(_b("%s mcdonalds farm [\n" % keyword)) self.protocol.lineReceived(_b(" ]\n")) self.protocol.lineReceived(_b("]\n")) self.check_success_or_xfail(as_success, "]\n")
def _addOutcome(self, outcome, test, error=None, details=None, error_permitted=True): """Report a failure in test test. Only one of error and details should be provided: conceptually there are two separate methods: addOutcome(self, test, error) addOutcome(self, test, details) :param outcome: A string describing the outcome - used as the event name in the subunit stream. :param error: Standard unittest positional argument form - an exc_info tuple. :param details: New Testing-in-python drafted API; a dict from string to subunit.Content objects. :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: " % outcome) + self._test_id(test)) if error_permitted: if error is None and details is None: raise ValueError else: if error is not None: raise ValueError if error is not None: self._stream.write(self._start_simple) tb_content = TracebackContent(error, test) for bytes in tb_content.iter_bytes(): self._stream.write(bytes) elif details is not None: self._write_details(details) else: self._stream.write(_b("\n")) if details is not None or error is not None: self._stream.write(self._end_simple)
def test_success_empty_message(self): self.protocol.lineReceived(_b("success mcdonalds farm [\n")) self.protocol.lineReceived(_b("]\n")) details = {} details['message'] = Content(ContentType("text", "plain"), lambda:[_b("")]) self.assertSuccess(details)
def skip_quoted_bracket(self, keyword): # This tests it is accepted, but cannot test it is used today, because # of not having a way to expose it in Python so far. self.protocol.lineReceived(_b("%s mcdonalds farm [\n" % keyword)) self.protocol.lineReceived(_b(" ]\n")) self.protocol.lineReceived(_b("]\n")) self.assertSkip(_b("]\n"))
def test_long_bytes(self): one_line_b = self._long_b.replace(_b("\n"), _b(" ")) mismatch = _BinaryMismatch(one_line_b, "!~", self._long_b) self.assertEqual(mismatch.describe(), "%s:\nreference = %s\nactual = %s\n" % ("!~", text_repr(one_line_b), text_repr(self._long_b, multiline=True)))
def test_time_accepted_stdlib(self): self.result = Python26TestResult() self.stream = BytesIO() self.protocol = subunit.TestProtocolServer(self.result, stream=self.stream) self.protocol.lineReceived(_b("time: 2001-12-12 12:59:59Z\n")) self.assertEqual(_b(""), self.stream.getvalue())
def test_from_file(self): fd, path = tempfile.mkstemp() self.addCleanup(os.remove, path) os.write(fd, _b("some data")) os.close(fd) content = content_from_file(path, UTF8_TEXT, chunk_size=2) self.assertThat(list(content.iter_bytes()), Equals([_b("so"), _b("me"), _b(" d"), _b("at"), _b("a")]))
def __init__(self, output, strict=True): """Create a decoder decoding to output. :param output: A file-like object. Bytes written to the Decoder are decoded to strip off the chunking and written to the output. Up to a full write worth of data or a single control line may be buffered (whichever is larger). The close method should be called when no more data is available, to detect short streams; the write method will return none-None when the end of a stream is detected. The output object must accept bytes objects. :param strict: If True (the default), the decoder will not knowingly accept input that is not conformant to the HTTP specification. (This does not imply that it will catch every nonconformance.) If False, it will accept incorrect input that is still unambiguous. """ self.output = output self.buffered_bytes = [] self.state = self._read_length self.body_length = 0 self.strict = strict self._match_chars = _b("0123456789abcdefABCDEF\r\n") self._slash_n = _b('\n') self._slash_r = _b('\r') self._slash_rn = _b('\r\n') self._slash_nr = _b('\n\r')
def __init__(self, client, stream=None, forward_stream=None): """Create a TestProtocolServer instance. :param client: An object meeting the unittest.TestResult protocol. :param stream: The stream that lines received which are not part of the subunit protocol should be written to. This allows custom handling of mixed protocols. By default, sys.stdout will be used for convenience. It should accept bytes to its write() method. :param forward_stream: A stream to forward subunit lines to. This allows a filter to forward the entire stream while still parsing and acting on it. By default forward_stream is set to DiscardStream() and no forwarding happens. """ self.client = ExtendedToOriginalDecorator(client) if stream is None: stream = sys.stdout if sys.version_info > (3, 0): stream = stream.buffer self._stream = stream self._forward_stream = forward_stream or DiscardStream() # state objects we can switch too self._in_test = _InTest(self) self._outside_test = _OutSideTest(self) self._reading_error_details = _ReadingErrorDetails(self) self._reading_failure_details = _ReadingFailureDetails(self) self._reading_skip_details = _ReadingSkipDetails(self) self._reading_success_details = _ReadingSuccessDetails(self) self._reading_xfail_details = _ReadingExpectedFailureDetails(self) self._reading_uxsuccess_details = _ReadingUnexpectedSuccessDetails(self) # start with outside test. self._state = self._outside_test # Avoid casts on every call self._plusminus = _b('+-') self._push_sym = _b('push') self._pop_sym = _b('pop')
def test_failure_empty_message(self): self.protocol.lineReceived(_b("failure mcdonalds farm [\n")) self.protocol.lineReceived(_b("]\n")) details = {} details['traceback'] = Content(ContentType("text", "x-traceback", {'charset': 'utf8'}), lambda:[_b("")]) self.assertFailure(details)
def test_calls_list_tests(self): ui, cmd = self.get_test_ui_and_cmd(args=('--', 'bar', 'quux')) cmd.repository_factory = memory.RepositoryFactory() if v2_avail: buffer = BytesIO() stream = subunit.StreamResultToBytes(buffer) stream.status(test_id='returned', test_status='exists') stream.status(test_id='values', test_status='exists') subunit_bytes = buffer.getvalue() else: subunit_bytes = _b('returned\n\nvalues\n') ui.proc_outputs = [subunit_bytes] self.setup_repo(cmd, ui) self.set_config( '[DEFAULT]\ntest_command=foo $LISTOPT $IDOPTION\n' 'test_id_option=--load-list $IDFILE\n' 'test_list_option=--list\n') self.assertEqual(0, cmd.execute()) expected_cmd = 'foo --list bar quux' self.assertEqual([ ('values', [('running', expected_cmd)]), ('popen', (expected_cmd,), {'shell': True, 'stdout': PIPE, 'stdin': PIPE}), ('communicate',), ('stream', _b('returned\nvalues\n')), ], ui.outputs)
def failure_quoted_bracket(self, keyword): self.protocol.lineReceived(_b("%s mcdonalds farm [\n" % keyword)) self.protocol.lineReceived(_b(" ]\n")) self.protocol.lineReceived(_b("]\n")) details = {} details['traceback'] = Content(ContentType("text", "x-traceback", {'charset': 'utf8'}), lambda:[_b("]\n")]) self.assertFailure(details)
def addSkip(self, test, reason=None, details=None): """Report a skipped test.""" if reason is None: self._addOutcome("skip", test, error=None, details=details) else: self._stream.write(_b("skip: %s [\n" % test.id())) self._stream.write(_b("%s\n" % reason)) self._stream.write(self._end_simple)
def test_decode_newline_nonstrict(self): """Tolerate chunk markers with no CR character.""" # From <http://pad.lv/505078> self.decoder = subunit.chunked.Decoder(self.output, strict=False) self.assertEqual(None, self.decoder.write(_b('a\n'))) self.assertEqual(None, self.decoder.write(_b('abcdeabcde'))) self.assertEqual(_b(''), self.decoder.write(_b('0\n'))) self.assertEqual(_b('abcdeabcde'), self.output.getvalue())
def tags(self, new_tags, gone_tags): """Inform the client about tags added/removed from the stream.""" if not new_tags and not gone_tags: return tags = set([tag.encode('utf8') for tag in new_tags]) tags.update([_b("-") + tag.encode('utf8') for tag in gone_tags]) tag_line = _b("tags: ") + _b(" ").join(tags) + _b("\n") self._stream.write(tag_line)
def test_keywords_after_success(self): self.protocol.lineReceived(_b("test old mcdonald\n")) self.protocol.lineReceived(_b("success old mcdonald\n")) self.keywords_before_test() self.assertEqual([ ('startTest', self.test), ('addSuccess', self.test), ('stopTest', self.test), ], self.client._events)
def test_keywords_after_failure(self): self.protocol.lineReceived(_b("test old mcdonald\n")) self.protocol.lineReceived(_b("failure old mcdonald\n")) self.keywords_before_test() self.assertEqual(self.client._events, [ ('startTest', self.test), ('addFailure', self.test, {}), ('stopTest', self.test), ])
def test_keywords_after_error(self): self.protocol.lineReceived(_b("test old mcdonald\n")) self.protocol.lineReceived(_b("error old mcdonald\n")) self.keywords_before_test() self.assertEqual([ ('startTest', self.test), ('addError', self.test, {}), ('stopTest', self.test), ], self.client._events)
def test_lost_connection_after_success(self): self.protocol.lineReceived(_b("test old mcdonald\n")) self.protocol.lineReceived(_b("success old mcdonald\n")) self.protocol.lostConnection() self.assertEqual([ ('startTest', self.test), ('addSuccess', self.test), ('stopTest', self.test), ], self.client._events)
def test_not_command(self): client = unittest.TestResult() out = BytesIO() protocol = subunit.TestProtocolServer(client, stream=subunit.DiscardStream(), forward_stream=out) pipe = BytesIO(_b("success old mcdonald\n")) protocol.readFrom(pipe) self.assertEqual(client.testsRun, 0) self.assertEqual(_b(""), out.getvalue())
def test_from_file_with_whence_seek(self): f = tempfile.NamedTemporaryFile() f.write(_b('some data')) f.flush() self.addCleanup(f.close) content = content_from_file( f.name, UTF8_TEXT, chunk_size=50, seek_offset=-4, seek_whence=2) self.assertThat( list(content.iter_bytes()), Equals([_b('data')]))
def test_from_stream_eager_loading(self): fd, path = tempfile.mkstemp() self.addCleanup(os.remove, path) os.write(fd, _b("some data")) stream = open(path, "rb") content = content_from_stream(stream, UTF8_TEXT, buffer_now=True) os.write(fd, _b("more data")) os.close(fd) self.assertThat("".join(content.iter_text()), Equals("some data"))
def test_lost_connected_after_failure(self): self.protocol.lineReceived(_b("test old mcdonald\n")) self.protocol.lineReceived(_b("failure old mcdonald\n")) self.protocol.lostConnection() self.assertEqual([ ('startTest', self.test), ('addFailure', self.test, subunit.RemoteError(_u(""))), ('stopTest', self.test), ], self.client._events)
def test_progress_accepted_stdlib(self): self.result = Python26TestResult() self.stream = BytesIO() self.protocol = subunit.TestProtocolServer(self.result, stream=self.stream) self.protocol.lineReceived(_b("progress: 23")) self.protocol.lineReceived(_b("progress: -2")) self.protocol.lineReceived(_b("progress: +4")) self.assertEqual(_b(""), self.stream.getvalue())
def success_quoted_bracket(self, keyword): # This tests it is accepted, but cannot test it is used today, because # of not having a way to expose it in Python so far. self.protocol.lineReceived(_b("%s mcdonalds farm [\n" % keyword)) self.protocol.lineReceived(_b(" ]\n")) self.protocol.lineReceived(_b("]\n")) details = {} details['message'] = Content(ContentType("text", "plain"), lambda:[_b("]\n")]) self.assertSuccess(details)
def test_TestCommand_cleanUp_disposes_instances_fail_raises(self): ui, command = self.get_test_ui_and_cmd() ui.proc_results = [1] self.set_config( '[DEFAULT]\ntest_command=foo\n' 'instance_dispose=bar $INSTANCE_IDS\n') command._instances.update([_b('baz'), _b('quux')]) self.assertThat(command.cleanUp, raises(ValueError('Disposing of instances failed, return 1'))) command.setUp()
def test_iter_streams_load_stdin_use_case(self): # A UI can be asked for the streams that a command has indicated it # accepts, which is what load < foo will require. ui = self.ui_factory([('subunit', _b('test: foo\nsuccess: foo\n'))]) cmd = commands.Command(ui) cmd.input_streams = ['subunit+'] ui.set_command(cmd) results = [] for result in ui.iter_streams('subunit'): results.append(result.read()) self.assertEqual([_b('test: foo\nsuccess: foo\n')], results)
def test_error_empty_message(self): self.protocol.lineReceived(_b("error mcdonalds farm [\n")) self.protocol.lineReceived(_b("]\n")) details = {} details['traceback'] = Content(ContentType("text", "x-traceback", {'charset': 'utf8'}), lambda:[_b("")]) self.assertEqual([ ('startTest', self.test), ('addError', self.test, details), ('stopTest', self.test), ], self.client._events)
def test_time_accepted_extended(self): self.result = ExtendedTestResult() self.stream = BytesIO() self.protocol = subunit.TestProtocolServer(self.result, stream=self.stream) self.protocol.lineReceived(_b("time: 2001-12-12 12:59:59Z\n")) self.assertEqual(_b(""), self.stream.getvalue()) self.assertEqual([ ('time', datetime.datetime(2001, 12, 12, 12, 59, 59, 0, iso8601.Utc())) ], self.result._events)
def test_from_stream_eager_loading(self): fd, path = tempfile.mkstemp() self.addCleanup(os.remove, path) self.addCleanup(os.close, fd) os.write(fd, _b('some data')) stream = open(path, 'rb') self.addCleanup(stream.close) content = content_from_stream(stream, UTF8_TEXT, buffer_now=True) os.write(fd, _b('more data')) self.assertThat( ''.join(content.iter_text()), Equals('some data'))
def test_communicate_with_timeout(self): proc = FakeProcess({}, {'stdout': BytesIO(_b('foo'))}) self.assertEqual((_b('foo'), ''), proc.communicate(timeout=10))
def __init__(self, parser): self.parser = parser self._test_sym = (_b('test'), _b('testing')) self._colon_sym = _b(':') self._error_sym = (_b('error'), ) self._failure_sym = (_b('failure'), ) self._progress_sym = (_b('progress'), ) self._skip_sym = _b('skip') self._success_sym = (_b('success'), _b('successful')) self._tags_sym = (_b('tags'), ) self._time_sym = (_b('time'), ) self._xfail_sym = (_b('xfail'), ) self._uxsuccess_sym = (_b('uxsuccess'), ) self._start_simple = _u(" [") self._start_multipart = _u(" [ multipart")
def test_communicate_with_out(self): proc = FakeProcess({}, {'stdout': BytesIO(_b('foo'))}) self.assertEqual((_b('foo'), ''), proc.communicate()) self.assertEqual(0, proc.returncode)
def test_communicate_with_input(self): proc = FakeProcess({}, {'stdout': BytesIO(_b('foo'))}) self.assertEqual((_b('foo'), ''), proc.communicate(input=_b("bar")))
def test_progress_pos_cur(self): self.protocol.progress(23, subunit.PROGRESS_CUR) self.assertEqual(self.io.getvalue(), _b('progress: +23\n'))
def test_add_success(self): """Test addSuccess on a TestProtocolClient.""" self.protocol.addSuccess(self.test) self.assertEqual(self.io.getvalue(), _b("successful: %s\n" % self.test.id()))
def test_add_skip(self): """Test addSkip on a TestProtocolClient.""" self.protocol.addSkip(self.test, "Has it really?") self.assertEqual( self.io.getvalue(), _b('skip: %s [\nHas it really?\n]\n' % self.test.id()))
def test_decode_combines_short(self): self.assertEqual(_b(''), self.decoder.write(_b('6\r\nabcdef0\r\n'))) self.assertEqual(_b('abcdef'), self.output.getvalue())
def test_start_test(self): """Test startTest on a TestProtocolClient.""" self.protocol.startTest(self.test) self.assertEqual(self.io.getvalue(), _b("test: %s\n" % self.test.id()))
def test_decode_excess_bytes_from_write(self): self.assertEqual(_b('1234'), self.decoder.write(_b('3\r\nabc0\r\n1234'))) self.assertEqual(_b('abc'), self.output.getvalue())
def setUp(self): fixtures.Fixture.setUp(self) self.addCleanup(delattr, self, 'content') self.content = [_b('content available until cleanUp')] self.addDetail('content', content.Content(content_type.UTF8_TEXT, self.get_content))
def test_decode_write_after_finished_errors(self): self.assertEqual(_b('1234'), self.decoder.write(_b('3\r\nabc0\r\n1234'))) self.assertRaises(ValueError, self.decoder.write, _b(''))
def test_decode_hex(self): self.assertEqual(_b(''), self.decoder.write(_b('A\r\n12345678900\r\n'))) self.assertEqual(_b('1234567890'), self.output.getvalue())
def test_decode_strict_newline_only(self): """Reject chunk markers with no CR character in strict mode.""" # From <http://pad.lv/505078> self.assertRaises(ValueError, self.decoder.write, _b('a\n'))
def test_stop_test(self): # stopTest doesn't output anything. self.protocol.stopTest(self.test) self.assertEqual(self.io.getvalue(), _b(""))
def read(self, len=0): return _b('')
def test_start_testing(self): self.protocol.lineReceived(_b("testing old mcdonald\n")) self.assertEqual( self.client._events, [('startTest', subunit.RemotedTestCase("old mcdonald"))])
def test_decode_short(self): self.assertEqual(_b(''), self.decoder.write(_b('3\r\nabc0\r\n'))) self.assertEqual(_b('abc'), self.output.getvalue())
def test_progress_set(self): self.protocol.progress(23, subunit.PROGRESS_SET) self.assertEqual(self.io.getvalue(), _b('progress: 23\n'))
def test_describe_non_ascii_bytes(self): string = _b("A\xA7") suffix = _b("B\xA7") mismatch = DoesNotEndWith(string, suffix) self.assertEqual("%r does not end with %r." % (string, suffix), mismatch.describe())
def test_communicate_with_input_and_stdin(self): stdin = BytesIO() proc = FakeProcess({}, {'stdin': stdin}) proc.communicate(input=_b("hello")) self.assertEqual(_b("hello"), stdin.getvalue())
def test_str_with_bytes(self): b = _b("\xA7") matcher = EndsWith(b) self.assertEqual("EndsWith(%r)" % (b, ), str(matcher))
def test_decode_serialised_form(self): self.assertEqual(None, self.decoder.write(_b("F\r\n"))) self.assertEqual(None, self.decoder.write(_b("serialised\n"))) self.assertEqual(_b(''), self.decoder.write(_b("form0\r\n")))
class Test_BinaryMismatch(TestCase): """Mismatches from binary comparisons need useful describe output""" _long_string = "This is a longish multiline non-ascii string\n\xa7" _long_b = _b(_long_string) _long_u = _u(_long_string) class CustomRepr(object): def __init__(self, repr_string): self._repr_string = repr_string def __repr__(self): return _u('<object ') + _u(self._repr_string) + _u('>') def test_short_objects(self): o1, o2 = self.CustomRepr('a'), self.CustomRepr('b') mismatch = _BinaryMismatch(o1, "!~", o2) self.assertEqual(mismatch.describe(), "%r !~ %r" % (o1, o2)) def test_short_mixed_strings(self): b, u = _b("\xa7"), _u("\xa7") mismatch = _BinaryMismatch(b, "!~", u) self.assertEqual(mismatch.describe(), "%r !~ %r" % (b, u)) def test_long_bytes(self): one_line_b = self._long_b.replace(_b("\n"), _b(" ")) mismatch = _BinaryMismatch(one_line_b, "!~", self._long_b) self.assertEqual( mismatch.describe(), "%s:\nreference = %s\nactual = %s\n" % ( "!~", text_repr(self._long_b, multiline=True), text_repr(one_line_b), )) def test_long_unicode(self): one_line_u = self._long_u.replace("\n", " ") mismatch = _BinaryMismatch(one_line_u, "!~", self._long_u) self.assertEqual( mismatch.describe(), "%s:\nreference = %s\nactual = %s\n" % ( "!~", text_repr(self._long_u, multiline=True), text_repr(one_line_u), )) def test_long_mixed_strings(self): mismatch = _BinaryMismatch(self._long_b, "!~", self._long_u) self.assertEqual( mismatch.describe(), "%s:\nreference = %s\nactual = %s\n" % ( "!~", text_repr(self._long_u, multiline=True), text_repr(self._long_b, multiline=True), )) def test_long_bytes_and_object(self): obj = object() mismatch = _BinaryMismatch(self._long_b, "!~", obj) self.assertEqual( mismatch.describe(), "%s:\nreference = %s\nactual = %s\n" % ( "!~", repr(obj), text_repr(self._long_b, multiline=True), )) def test_long_unicode_and_object(self): obj = object() mismatch = _BinaryMismatch(self._long_u, "!~", obj) self.assertEqual( mismatch.describe(), "%s:\nreference = %s\nactual = %s\n" % ( "!~", repr(obj), text_repr(self._long_u, multiline=True), ))
def test_decode_nothing(self): self.assertEqual(_b(''), self.decoder.write(_b('0\r\n'))) self.assertEqual(_b(''), self.output.getvalue())
def test_short_mixed_strings(self): b, u = _b("\xa7"), _u("\xa7") mismatch = _BinaryMismatch(b, "!~", u) self.assertEqual(mismatch.describe(), "%r !~ %r" % (b, u))
def startTest(self, test): """Mark a test as starting its test run.""" super(TestProtocolClient, self).startTest(test) self._stream.write(_b("test: ") + self._test_id(test) + _b("\n")) self._stream.flush()
from extras import try_import from testtools.compat import ( _b, _format_exception_only, _format_stack_list, _isbytes, _TB_HEADER, _u, str_is_unicode, ) from testtools.content_type import ContentType, JSON, UTF8_TEXT functools = try_import('functools') _join_b = _b("").join DEFAULT_CHUNK_SIZE = 4096 STDOUT_LINE = '\nStdout:\n%s' STDERR_LINE = '\nStderr:\n%s' def _iter_chunks(stream, chunk_size, seek_offset=None, seek_whence=0): """Read 'stream' in chunks of 'chunk_size'. :param stream: A file-like object to read from. :param chunk_size: The size of each read from 'stream'. :param seek_offset: If non-None, seek before iterating. :param seek_whence: Pass through to the seek call, if seeking. """
def readlines(stream): return _b('').join(stream.readlines())
def test_foo(self): self.useFixture(fixture) # Add a colliding detail (both should show up) self.addDetail('content', content.Content(content_type.UTF8_TEXT, lambda:[_b('foo')]))