1
0
mirror of https://github.com/samba-team/samba.git synced 2025-08-07 09:49:30 +03:00

subunit: Import latest upstream.

This commit is contained in:
Jelmer Vernooij
2010-09-04 23:04:28 +02:00
parent ed42535041
commit 5de2ec0def
13 changed files with 300 additions and 118 deletions

21
lib/subunit/MANIFEST.in Normal file
View File

@ -0,0 +1,21 @@
exclude .bzrignore
exclude aclocal.m4
prune autom4te.cache
prune c
prune c++
prune compile
exclude configure*
exclude depcomp
exclude INSTALL
exclude install-sh
exclude lib*
exclude ltmain.sh
prune m4
exclude Makefile*
exclude missing
prune perl
exclude py-compile
prune shell
prune python/iso8601
exclude stamp-h1
include NEWS

View File

@ -5,9 +5,20 @@ subunit release notes
NEXT (In development)
---------------------
0.0.6
-----
This release of subunit fixes a number of unicode related bugs. This depends on
testtools 0.9.4 and will not function without it. Thanks to Tres Seaver there
is also an optional native setup.py file for use with easy_install and the
like.
BUG FIXES
~~~~~~~~~
* Be consistent about delivering unicode content to testtools StringException
class which has become (appropriately) conservative. (Robert Collins)
* Fix incorrect reference to subunit_test_failf in c/README.
(Brad Hards, #524341)
@ -15,6 +26,28 @@ BUG FIXES
is purely cosmetic as the parameters are passed down with no interpretation.
(Robert Collins, #537611)
* Old style tracebacks with no encoding info are now treated as UTF8 rather
than some-random-codec-like-ascii. (Robert Collins)
* On windows, ProtocolTestCase and TestProtocolClient will set their streams to
binary mode by calling into msvcrt; this avoids having their input or output
mangled by the default line ending translation on that platform.
(Robert Collins, Martin [gz], #579296)
IMPROVEMENTS
~~~~~~~~~~~~
* Subunit now has a setup.py for python deployments that are not using
distribution packages. (Tres Seaver, #538181)
* Subunit now supports test discovery by building on the testtools support for
it. You can take advantage of it with "python -m subunit.run discover [path]"
and see "python -m subunit.run discover --help" for more options.
* Subunit now uses the improved unicode support in testtools when outputting
non-details based test information; this should consistently UTF8 encode such
strings.
0.0.5
-----

View File

@ -160,7 +160,7 @@ tags: [-]TAG ...
time: YYYY-MM-DD HH:MM:SSZ
DETAILS ::= BRACKETED | MULTIPART
BRACKETED ::= '[' CR lines ']' CR
BRACKETED ::= '[' CR UTF8-lines ']' CR
MULTIPART ::= '[ multipart' CR PART* ']' CR
PART ::= PART_TYPE CR NAME CR PART_BYTES CR
PART_TYPE ::= Content-Type: type/sub-type(;parameter=value,parameter=value)

View File

@ -1,6 +1,6 @@
m4_define([SUBUNIT_MAJOR_VERSION], [0])
m4_define([SUBUNIT_MINOR_VERSION], [0])
m4_define([SUBUNIT_MICRO_VERSION], [5])
m4_define([SUBUNIT_MICRO_VERSION], [6])
m4_define([SUBUNIT_VERSION],
m4_defn([SUBUNIT_MAJOR_VERSION]).m4_defn([SUBUNIT_MINOR_VERSION]).m4_defn([SUBUNIT_MICRO_VERSION]))
AC_PREREQ([2.59])

View File

@ -18,58 +18,9 @@
from optparse import OptionParser
import sys
import unittest
from subunit import DiscardStream, ProtocolTestCase
class TestIdPrintingResult(unittest.TestResult):
def __init__(self, stream, show_times=False):
"""Create a FilterResult object outputting to stream."""
unittest.TestResult.__init__(self)
self._stream = stream
self.failed_tests = 0
self.__time = 0
self.show_times = show_times
self._test = None
self._test_duration = 0
def addError(self, test, err):
self.failed_tests += 1
self._test = test
def addFailure(self, test, err):
self.failed_tests += 1
self._test = test
def addSuccess(self, test):
self._test = test
def reportTest(self, test, duration):
if self.show_times:
seconds = duration.seconds
seconds += duration.days * 3600 * 24
seconds += duration.microseconds / 1000000.0
self._stream.write(test.id() + ' %0.3f\n' % seconds)
else:
self._stream.write(test.id() + '\n')
def startTest(self, test):
self._start_time = self._time()
def stopTest(self, test):
test_duration = self._time() - self._start_time
self.reportTest(self._test, test_duration)
def time(self, time):
self.__time = time
def _time(self):
return self.__time
def wasSuccessful(self):
"Tells whether or not this result was a success"
return self.failed_tests == 0
from subunit.test_results import TestIdPrintingResult
parser = OptionParser(description=__doc__)

View File

@ -159,4 +159,25 @@ sub report_time($)
printf "time: %04d-%02d-%02d %02d:%02d:%02dZ\n", $year+1900, $mon, $mday, $hour, $min, $sec;
}
sub progress_pop()
{
print "progress: pop\n";
}
sub progress_push()
{
print "progress: push\n";
}
sub progress($;$)
{
my ($count, $whence) = @_;
unless(defined($whence)) {
$whence = "";
}
print "progress: $whence$count\n";
}
1;

View File

@ -133,9 +133,7 @@ try:
except ImportError:
raise ImportError ("testtools.testresult.real does not contain "
"_StringException, check your version.")
from testtools.testresult.real import _StringException
from testtools import testresult
import chunked, details, test_results
@ -244,7 +242,7 @@ class _ParserState(object):
def lostConnection(self):
"""Connection lost."""
self.parser._lostConnectionInTest('unknown state of ')
self.parser._lostConnectionInTest(u'unknown state of ')
def startTest(self, offset, line):
"""A test start command received."""
@ -324,7 +322,7 @@ class _InTest(_ParserState):
def lostConnection(self):
"""Connection lost."""
self.parser._lostConnectionInTest('')
self.parser._lostConnectionInTest(u'')
class _OutSideTest(_ParserState):
@ -359,7 +357,7 @@ class _ReadingDetails(_ParserState):
def lostConnection(self):
"""Connection lost."""
self.parser._lostConnectionInTest('%s report of ' %
self.parser._lostConnectionInTest(u'%s report of ' %
self._outcome_label())
def _outcome_label(self):
@ -501,7 +499,7 @@ class TestProtocolServer(object):
self._state.lineReceived(line)
def _lostConnectionInTest(self, state_string):
error_string = "lost connection during %stest '%s'" % (
error_string = u"lost connection during %stest '%s'" % (
state_string, self.current_test_description)
self.client.addError(self._current_test, RemoteError(error_string))
self.client.stopTest(self._current_test)
@ -531,7 +529,7 @@ class TestProtocolServer(object):
self._stream.write(line)
class TestProtocolClient(unittest.TestResult):
class TestProtocolClient(testresult.TestResult):
"""A TestResult which generates a subunit stream for a test run.
# Get a TestSuite or TestCase to run
@ -550,8 +548,9 @@ class TestProtocolClient(unittest.TestResult):
"""
def __init__(self, stream):
unittest.TestResult.__init__(self)
testresult.TestResult.__init__(self)
self._stream = stream
_make_stream_binary(stream)
def addError(self, test, error=None, details=None):
"""Report an error in test test.
@ -618,8 +617,10 @@ class TestProtocolClient(unittest.TestResult):
raise ValueError
if error is not None:
self._stream.write(" [\n")
for line in self._exc_info_to_string(error, test).splitlines():
self._stream.write("%s\n" % line)
# XXX: this needs to be made much stricter, along the lines of
# Martin[gz]'s work in testtools. Perhaps subunit can use that?
for line in self._exc_info_to_unicode(error, test).splitlines():
self._stream.write(("%s\n" % line).encode('utf8'))
else:
self._write_details(details)
self._stream.write("]\n")
@ -704,7 +705,7 @@ class TestProtocolClient(unittest.TestResult):
"""Obey the testtools result.done() interface."""
def RemoteError(description=""):
def RemoteError(description=u""):
return (_StringException, _StringException(description), None)
@ -754,7 +755,7 @@ class RemotedTestCase(unittest.TestCase):
def run(self, result=None):
if result is None: result = self.defaultTestResult()
result.startTest(self)
result.addError(self, RemoteError("Cannot run RemotedTestCases.\n"))
result.addError(self, RemoteError(u"Cannot run RemotedTestCases.\n"))
result.stopTest(self)
def _strclass(self):
@ -784,7 +785,7 @@ class ExecTestCase(unittest.TestCase):
def debug(self):
"""Run the test without collecting errors in a TestResult"""
self._run(unittest.TestResult())
self._run(testresult.TestResult())
def _run(self, result):
protocol = TestProtocolServer(result)
@ -816,7 +817,7 @@ class IsolatedTestSuite(unittest.TestSuite):
"""
def run(self, result=None):
if result is None: result = unittest.TestResult()
if result is None: result = testresult.TestResult()
run_isolated(unittest.TestSuite, self, result)
@ -1045,8 +1046,10 @@ class ProtocolTestCase(object):
subunit input is not forwarded.
"""
self._stream = stream
_make_stream_binary(stream)
self._passthrough = passthrough
self._forward = forward
_make_stream_binary(forward)
def __call__(self, result=None):
return self.run(result)
@ -1062,7 +1065,7 @@ class ProtocolTestCase(object):
protocol.lostConnection()
class TestResultStats(unittest.TestResult):
class TestResultStats(testresult.TestResult):
"""A pyunit TestResult interface implementation for making statistics.
:ivar total_tests: The total tests seen.
@ -1073,7 +1076,7 @@ class TestResultStats(unittest.TestResult):
def __init__(self, stream):
"""Create a TestResultStats which outputs to stream."""
unittest.TestResult.__init__(self)
testresult.TestResult.__init__(self)
self._stream = stream
self.failed_tests = 0
self.skipped_tests = 0
@ -1124,3 +1127,14 @@ def get_default_formatter():
else:
return sys.stdout
def _make_stream_binary(stream):
"""Ensure that a stream will be binary safe. See _make_binary_on_windows."""
if getattr(stream, 'fileno', None) is not None:
_make_binary_on_windows(stream.fileno())
def _make_binary_on_windows(fileno):
"""Win32 mangles \r\n to \n and that breaks streams. See bug lp:505078."""
if sys.platform == "win32":
import msvcrt
msvcrt.setmode(fileno, os.O_BINARY)

View File

@ -47,8 +47,12 @@ class SimpleDetailsParser(DetailsParser):
def get_details(self, style=None):
result = {}
if not style:
# We know that subunit/testtools serialise [] formatted
# tracebacks as utf8, but perhaps we need a ReplacingContent
# or something like that.
result['traceback'] = content.Content(
content_type.ContentType("text", "x-traceback"),
content_type.ContentType("text", "x-traceback",
{"charset": "utf8"}),
lambda:[self._message])
else:
if style == 'skip':
@ -92,7 +96,7 @@ class MultipartDetailsParser(DetailsParser):
residue = self._chunk_parser.write(line)
if residue is not None:
# Line based use always ends on no residue.
assert residue == ''
assert residue == '', 'residue: %r' % (residue,)
body = self._body
self._details[self._name] = content.Content(
self._content_type, lambda:[body.getvalue()])

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/python
#
# Simple subunit testrunner for python
# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
@ -23,6 +23,13 @@
import sys
from subunit import TestProtocolClient, get_default_formatter
from testtools.run import (
BUFFEROUTPUT,
CATCHBREAK,
FAILFAST,
TestProgram,
USAGE_AS_MAIN,
)
class SubunitTestRunner(object):
@ -36,12 +43,30 @@ class SubunitTestRunner(object):
return result
class SubunitTestProgram(TestProgram):
USAGE = USAGE_AS_MAIN
def usageExit(self, msg=None):
if msg:
print msg
usage = {'progName': self.progName, 'catchbreak': '', 'failfast': '',
'buffer': ''}
if self.failfast != False:
usage['failfast'] = FAILFAST
if self.catchbreak != False:
usage['catchbreak'] = CATCHBREAK
if self.buffer != False:
usage['buffer'] = BUFFEROUTPUT
usage_text = self.USAGE % usage
usage_lines = usage_text.split('\n')
usage_lines.insert(2, "Run a test suite with a subunit reporter.")
usage_lines.insert(3, "")
print('\n'.join(usage_lines))
sys.exit(2)
if __name__ == '__main__':
import optparse
from unittest import TestProgram
parser = optparse.OptionParser(__doc__)
args = parser.parse_args()[1]
stream = get_default_formatter()
runner = SubunitTestRunner(stream)
program = TestProgram(module=None, argv=[sys.argv[0]] + args,
testRunner=runner)
SubunitTestProgram(module=None, argv=sys.argv, testRunner=runner)

View File

@ -6,7 +6,7 @@
# license at the users choice. A copy of both licenses are available in the
# project source as Apache-2.0 and BSD. You may not use this file except in
# compliance with one of these two licences.
#
#
# Unless required by applicable law or agreed to in writing, software
# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@ -21,16 +21,14 @@ import datetime
import iso8601
import testtools
import subunit
# NOT a TestResult, because we are implementing the interface, not inheriting
# it.
class TestResultDecorator(object):
"""General pass-through decorator.
This provides a base that other TestResults can inherit from to
gain basic forwarding functionality. It also takes care of
This provides a base that other TestResults can inherit from to
gain basic forwarding functionality. It also takes care of
handling the case where the target doesn't support newer methods
or features by degrading them.
"""
@ -201,11 +199,11 @@ class TestResultFilter(TestResultDecorator):
"""A pyunit TestResult interface implementation which filters tests.
Tests that pass the filter are handed on to another TestResult instance
for further processing/reporting. To obtain the filtered results,
for further processing/reporting. To obtain the filtered results,
the other instance must be interrogated.
:ivar result: The result that tests are passed to after filtering.
:ivar filter_predicate: The callback run to decide whether to pass
:ivar filter_predicate: The callback run to decide whether to pass
a result.
"""
@ -213,7 +211,7 @@ class TestResultFilter(TestResultDecorator):
filter_success=True, filter_skip=False,
filter_predicate=None):
"""Create a FilterResult object filtering to result.
:param filter_error: Filter out errors.
:param filter_failure: Filter out failures.
:param filter_success: Filter out successful tests.
@ -238,9 +236,9 @@ class TestResultFilter(TestResultDecorator):
self._current_test_filtered = None
# The (new, gone) tags for the current test.
self._current_test_tags = None
def addError(self, test, err=None, details=None):
if (not self._filter_error and
if (not self._filter_error and
self.filter_predicate(test, 'error', err, details)):
self.decorated.startTest(test)
self.decorated.addError(test, err, details=details)
@ -288,17 +286,17 @@ class TestResultFilter(TestResultDecorator):
def startTest(self, test):
"""Start a test.
Not directly passed to the client, but used for handling of tags
correctly.
"""
self._current_test = test
self._current_test_filtered = False
self._current_test_tags = set(), set()
def stopTest(self, test):
"""Stop a test.
Not directly passed to the client, but used for handling of tags
correctly.
"""
@ -316,7 +314,7 @@ class TestResultFilter(TestResultDecorator):
Adds and removes tags as appropriate. If a test is currently running,
tags are not affected for subsequent tests.
:param new_tags: Tags to add,
:param gone_tags: Tags to remove.
"""
@ -332,3 +330,53 @@ class TestResultFilter(TestResultDecorator):
if id.startswith("subunit.RemotedTestCase."):
return id[len("subunit.RemotedTestCase."):]
return id
class TestIdPrintingResult(testtools.TestResult):
def __init__(self, stream, show_times=False):
"""Create a FilterResult object outputting to stream."""
testtools.TestResult.__init__(self)
self._stream = stream
self.failed_tests = 0
self.__time = 0
self.show_times = show_times
self._test = None
self._test_duration = 0
def addError(self, test, err):
self.failed_tests += 1
self._test = test
def addFailure(self, test, err):
self.failed_tests += 1
self._test = test
def addSuccess(self, test):
self._test = test
def reportTest(self, test, duration):
if self.show_times:
seconds = duration.seconds
seconds += duration.days * 3600 * 24
seconds += duration.microseconds / 1000000.0
self._stream.write(test.id() + ' %0.3f\n' % seconds)
else:
self._stream.write(test.id() + '\n')
def startTest(self, test):
self._start_time = self._time()
def stopTest(self, test):
test_duration = self._time() - self._start_time
self.reportTest(self._test, test_duration)
def time(self, time):
self.__time = time
def _time(self):
return self.__time
def wasSuccessful(self):
"Tells whether or not this result was a success"
return self.failed_tests == 0

View File

@ -51,7 +51,8 @@ class TestSimpleDetails(unittest.TestCase):
traceback = ""
expected = {}
expected['traceback'] = content.Content(
content_type.ContentType("text", "x-traceback"),
content_type.ContentType("text", "x-traceback",
{'charset': 'utf8'}),
lambda:[""])
found = parser.get_details()
self.assertEqual(expected.keys(), found.keys())

View File

@ -102,6 +102,9 @@ class TestTestProtocolServerPipe(unittest.TestCase):
"------------\n\n")])
self.assertEqual(client.testsRun, 3)
def test_non_test_characters_forwarded_immediately(self):
pass
class TestTestProtocolServerStartTest(unittest.TestCase):
@ -243,7 +246,8 @@ class TestTestProtocolServerPassThrough(unittest.TestCase):
self.protocol.lineReceived("]\n")
self.assertEqual(self.stdout.getvalue(), "")
details = {}
details['traceback'] = Content(ContentType("text", "x-traceback"),
details['traceback'] = Content(ContentType("text", "x-traceback",
{'charset': 'utf8'}),
lambda:[
"test old mcdonald\n"
"failure a\n"
@ -285,7 +289,7 @@ class TestTestProtocolServerLostConnection(unittest.TestCase):
self.protocol.lineReceived("test old mcdonald\n")
self.protocol.lostConnection()
failure = subunit.RemoteError(
"lost connection during test 'old mcdonald'")
u"lost connection during test 'old mcdonald'")
self.assertEqual([
('startTest', self.test),
('addError', self.test, failure),
@ -298,7 +302,7 @@ class TestTestProtocolServerLostConnection(unittest.TestCase):
self.protocol.lostConnection()
self.assertEqual([
('startTest', self.test),
('addError', self.test, subunit.RemoteError("")),
('addError', self.test, subunit.RemoteError(u"")),
('stopTest', self.test),
], self.client._events)
@ -307,7 +311,7 @@ class TestTestProtocolServerLostConnection(unittest.TestCase):
self.protocol.lineReceived("%s old mcdonald %s" % (outcome, opening))
self.protocol.lostConnection()
failure = subunit.RemoteError(
"lost connection during %s report of test 'old mcdonald'" %
u"lost connection during %s report of test 'old mcdonald'" %
outcome)
self.assertEqual([
('startTest', self.test),
@ -327,7 +331,7 @@ class TestTestProtocolServerLostConnection(unittest.TestCase):
self.protocol.lostConnection()
self.assertEqual([
('startTest', self.test),
('addFailure', self.test, subunit.RemoteError("")),
('addFailure', self.test, subunit.RemoteError(u"")),
('stopTest', self.test),
], self.client._events)
@ -411,8 +415,8 @@ class TestTestProtocolServerAddError(unittest.TestCase):
self.protocol.lineReceived("error mcdonalds farm [\n")
self.protocol.lineReceived("]\n")
details = {}
details['traceback'] = Content(ContentType("text", "x-traceback"),
lambda:[""])
details['traceback'] = Content(ContentType("text", "x-traceback",
{'charset': 'utf8'}), lambda:[""])
self.assertEqual([
('startTest', self.test),
('addError', self.test, details),
@ -424,8 +428,8 @@ class TestTestProtocolServerAddError(unittest.TestCase):
self.protocol.lineReceived(" ]\n")
self.protocol.lineReceived("]\n")
details = {}
details['traceback'] = Content(ContentType("text", "x-traceback"),
lambda:["]\n"])
details['traceback'] = Content(ContentType("text", "x-traceback",
{'charset': 'utf8'}), lambda:["]\n"])
self.assertEqual([
('startTest', self.test),
('addError', self.test, details),
@ -469,8 +473,8 @@ class TestTestProtocolServerAddFailure(unittest.TestCase):
self.protocol.lineReceived("failure mcdonalds farm [\n")
self.protocol.lineReceived("]\n")
details = {}
details['traceback'] = Content(ContentType("text", "x-traceback"),
lambda:[""])
details['traceback'] = Content(ContentType("text", "x-traceback",
{'charset': 'utf8'}), lambda:[""])
self.assertFailure(details)
def failure_quoted_bracket(self, keyword):
@ -478,8 +482,8 @@ class TestTestProtocolServerAddFailure(unittest.TestCase):
self.protocol.lineReceived(" ]\n")
self.protocol.lineReceived("]\n")
details = {}
details['traceback'] = Content(ContentType("text", "x-traceback"),
lambda:["]\n"])
details['traceback'] = Content(ContentType("text", "x-traceback",
{'charset': 'utf8'}), lambda:["]\n"])
self.assertFailure(details)
def test_failure_quoted_bracket(self):
@ -535,12 +539,13 @@ class TestTestProtocolServerAddxFail(unittest.TestCase):
details = {}
if error_message is not None:
details['traceback'] = Content(
ContentType("text", "x-traceback"), lambda:[error_message])
ContentType("text", "x-traceback", {'charset': 'utf8'}),
lambda:[error_message])
if isinstance(self.client, ExtendedTestResult):
value = details
else:
if error_message is not None:
value = subunit.RemoteError('Text attachment: traceback\n'
value = subunit.RemoteError(u'Text attachment: traceback\n'
'------------\n' + error_message + '------------\n')
else:
value = subunit.RemoteError()
@ -845,15 +850,15 @@ class TestRemotedTestCase(unittest.TestCase):
class TestRemoteError(unittest.TestCase):
def test_eq(self):
error = subunit.RemoteError("Something went wrong")
another_error = subunit.RemoteError("Something went wrong")
different_error = subunit.RemoteError("boo!")
error = subunit.RemoteError(u"Something went wrong")
another_error = subunit.RemoteError(u"Something went wrong")
different_error = subunit.RemoteError(u"boo!")
self.assertEqual(error, another_error)
self.assertNotEqual(error, different_error)
self.assertNotEqual(different_error, another_error)
def test_empty_constructor(self):
self.assertEqual(subunit.RemoteError(), subunit.RemoteError(""))
self.assertEqual(subunit.RemoteError(), subunit.RemoteError(u""))
class TestExecTestCase(unittest.TestCase):
@ -887,8 +892,8 @@ class TestExecTestCase(unittest.TestCase):
mcdonald = subunit.RemotedTestCase("old mcdonald")
bing = subunit.RemotedTestCase("bing crosby")
bing_details = {}
bing_details['traceback'] = Content(ContentType("text", "x-traceback"),
lambda:["foo.c:53:ERROR invalid state\n"])
bing_details['traceback'] = Content(ContentType("text", "x-traceback",
{'charset': 'utf8'}), lambda:["foo.c:53:ERROR invalid state\n"])
an_error = subunit.RemotedTestCase("an error")
error_details = {}
self.assertEqual([
@ -1004,7 +1009,7 @@ class TestTestProtocolClient(unittest.TestCase):
ContentType('text', 'plain'), lambda:['serialised\nform'])}
self.sample_tb_details = dict(self.sample_details)
self.sample_tb_details['traceback'] = TracebackContent(
subunit.RemoteError("boo qux"), self.test)
subunit.RemoteError(u"boo qux"), self.test)
def test_start_test(self):
"""Test startTest on a TestProtocolClient."""
@ -1034,7 +1039,7 @@ class TestTestProtocolClient(unittest.TestCase):
def test_add_failure(self):
"""Test addFailure on a TestProtocolClient."""
self.protocol.addFailure(
self.test, subunit.RemoteError("boo qux"))
self.test, subunit.RemoteError(u"boo qux"))
self.assertEqual(
self.io.getvalue(),
('failure: %s [\n' + _remote_exception_str + ': boo qux\n]\n')
@ -1058,7 +1063,7 @@ class TestTestProtocolClient(unittest.TestCase):
def test_add_error(self):
"""Test stopTest on a TestProtocolClient."""
self.protocol.addError(
self.test, subunit.RemoteError("phwoar crikey"))
self.test, subunit.RemoteError(u"phwoar crikey"))
self.assertEqual(
self.io.getvalue(),
('error: %s [\n' +
@ -1083,7 +1088,7 @@ class TestTestProtocolClient(unittest.TestCase):
def test_add_expected_failure(self):
"""Test addExpectedFailure on a TestProtocolClient."""
self.protocol.addExpectedFailure(
self.test, subunit.RemoteError("phwoar crikey"))
self.test, subunit.RemoteError(u"phwoar crikey"))
self.assertEqual(
self.io.getvalue(),
('xfail: %s [\n' +

59
lib/subunit/setup.py Executable file
View File

@ -0,0 +1,59 @@
#!/usr/bin/env python
try:
# If the user has setuptools / distribute installed, use it
from setuptools import setup
except ImportError:
# Otherwise, fall back to distutils.
from distutils.core import setup
extra = {}
else:
extra = {
'install_requires': [
'testtools',
]
}
try:
# Assume we are in a distribution, which has PKG-INFO
version_lines = [x for x in open('PKG-INFO').readlines()
if x.startswith('Version:')]
version_line = version_lines and version_lines[-1] or 'VERSION = 0.0'
VERSION = version_line.split(':')[1].strip()
except IOError:
# Must be a development checkout, so use the Makefile
version_lines = [x for x in open('Makefile').readlines()
if x.startswith('VERSION')]
version_line = version_lines and version_lines[-1] or 'VERSION = 0.0'
VERSION = version_line.split('=')[1].strip()
setup(
name='python-subunit',
version=VERSION,
description=('Python implementation of subunit test streaming protocol'),
long_description=open('README').read(),
classifiers=[
'Intended Audience :: Developers',
'Programming Language :: Python',
'Topic :: Software Development :: Testing',
],
keywords='python test streaming',
author='Robert Collins',
author_email='subunit-dev@lists.launchpad.net',
url='http://launchpad.net/subunit',
packages=['subunit'],
package_dir={'subunit': 'python/subunit'},
scripts = [
'filters/subunit2gtk',
'filters/subunit2junitxml',
'filters/subunit2pyunit',
'filters/subunit-filter',
'filters/subunit-ls',
'filters/subunit-notify',
'filters/subunit-stats',
'filters/subunit-tags',
'filters/tap2subunit',
],
**extra
)