55
54
"""Indicates that a test was intentionally skipped, rather than failing."""
56
55
# XXX: Not used yet
58
class EarlyStoppingTestResultAdapter(object):
59
"""An adapter for TestResult to stop at the first first failure or error"""
61
def __init__(self, result):
64
def addError(self, test, err):
65
self._result.addError(test, err)
68
def addFailure(self, test, err):
69
self._result.addFailure(test, err)
72
def __getattr__(self, name):
73
return getattr(self._result, name)
75
def __setattr__(self, name, value):
77
object.__setattr__(self, name, value)
78
return setattr(self._result, name, value)
58
class TestCase(unittest.TestCase):
59
"""Base class for bzr unit tests.
61
Tests that need access to disk resources should subclass
62
FunctionalTestCase not TestCase.
65
# TODO: Special methods to invoke bzr, so that we can run it
66
# through a specified Python intepreter
68
OVERRIDE_PYTHON = None # to run with alternative python 'python'
72
super(TestCase, self).setUp()
73
# setup a temporary log for the test
77
self.TEST_LOG = tempfile.NamedTemporaryFile(mode='wt', bufsize=0)
78
# save stdout & stderr so there's no leakage from code-under-test
79
self.real_stdout = sys.stdout
80
self.real_stderr = sys.stderr
81
sys.stdout = sys.stderr = self.TEST_LOG
82
self.log("%s setup" % self.id())
85
sys.stdout = self.real_stdout
86
sys.stderr = self.real_stderr
87
self.log("%s teardown" % self.id())
89
super(TestCase, self).tearDown()
92
"""Log a message to a progress file"""
93
print >>self.TEST_LOG, msg
95
def check_inventory_shape(self, inv, shape):
97
Compare an inventory to a list of expected names.
99
Fail if they are not precisely equal.
102
shape = list(shape) # copy
103
for path, ie in inv.entries():
104
name = path.replace('\\', '/')
112
self.fail("expected paths not found in inventory: %r" % shape)
114
self.fail("unexpected paths found in inventory: %r" % extras)
117
"""Get the log the test case used. This can only be called once,
118
after which an exception will be raised.
120
self.TEST_LOG.flush()
121
log = open(self.TEST_LOG.name, 'rt').read()
122
self.TEST_LOG.close()
126
class FunctionalTestCase(TestCase):
127
"""Base class for tests that perform function testing - running bzr,
128
using files on disk, and similar activities.
130
InTempDir is an old alias for FunctionalTestCase.
136
def check_file_contents(self, filename, expect):
137
self.log("check contents of file %s" % filename)
138
contents = file(filename, 'r').read()
139
if contents != expect:
140
self.log("expected: %r" % expect)
141
self.log("actually: %r" % contents)
142
self.fail("contents of %s not as expected")
144
def _make_test_root(self):
149
if FunctionalTestCase.TEST_ROOT is not None:
151
FunctionalTestCase.TEST_ROOT = os.path.abspath(
152
tempfile.mkdtemp(suffix='.tmp',
153
prefix=self._TEST_NAME + '-',
156
# make a fake bzr directory there to prevent any tests propagating
157
# up onto the source directory's real branch
158
os.mkdir(os.path.join(FunctionalTestCase.TEST_ROOT, '.bzr'))
161
super(FunctionalTestCase, self).setUp()
163
self._make_test_root()
164
self._currentdir = os.getcwdu()
165
self.test_dir = os.path.join(self.TEST_ROOT, self.id())
166
os.mkdir(self.test_dir)
167
os.chdir(self.test_dir)
171
os.chdir(self._currentdir)
172
super(FunctionalTestCase, self).tearDown()
174
def formcmd(self, cmd):
175
if isinstance(cmd, basestring):
178
cmd[0] = self.BZRPATH
179
if self.OVERRIDE_PYTHON:
180
cmd.insert(0, self.OVERRIDE_PYTHON)
181
self.log('$ %r' % cmd)
184
def runcmd(self, cmd, retcode=0):
185
"""Run one command and check the return code.
187
Returns a tuple of (stdout,stderr) strings.
189
If a single string is based, it is split into words.
190
For commands that are not simple space-separated words, please
191
pass a list instead."""
194
from subprocess import call
195
except ImportError, e:
198
cmd = self.formcmd(cmd)
199
self.log('$ ' + ' '.join(cmd))
200
actual_retcode = call(cmd, stdout=self.TEST_LOG, stderr=self.TEST_LOG)
201
if retcode != actual_retcode:
202
raise CommandFailed("test failed: %r returned %d, expected %d"
203
% (cmd, actual_retcode, retcode))
205
def backtick(self, cmd, retcode=0):
206
"""Run a command and return its output"""
209
from subprocess import Popen, PIPE
210
except ImportError, e:
214
cmd = self.formcmd(cmd)
215
child = Popen(cmd, stdout=PIPE, stderr=self.TEST_LOG)
216
outd, errd = child.communicate()
218
actual_retcode = child.wait()
220
outd = outd.replace('\r', '')
222
if retcode != actual_retcode:
223
raise CommandFailed("test failed: %r returned %d, expected %d"
224
% (cmd, actual_retcode, retcode))
230
def build_tree(self, shape):
231
"""Build a test tree according to a pattern.
233
shape is a sequence of file specifications. If the final
234
character is '/', a directory is created.
236
This doesn't add anything to a branch.
238
# XXX: It's OK to just create them using forward slashes on windows?
241
assert isinstance(name, basestring)
246
print >>f, "contents of", name
249
InTempDir = FunctionalTestCase
81
252
class _MyResult(unittest._TextTestResult):
124
298
class TextTestRunner(unittest.TextTestRunner):
126
300
def _makeResult(self):
127
result = _MyResult(self.stream, self.descriptions, self.verbosity)
128
return EarlyStoppingTestResultAdapter(result)
131
class filteringVisitor(TestUtil.TestVisitor):
132
"""I accruse all the testCases I visit that pass a regexp filter on id
136
def __init__(self, filter):
138
TestUtil.TestVisitor.__init__(self)
140
self.filter=re.compile(filter)
143
"""answer the suite we are building"""
144
if self._suite is None:
145
self._suite=TestUtil.TestSuite()
148
def visitCase(self, aCase):
149
if self.filter.match(aCase.id()):
150
self.suite().addTest(aCase)
153
def run_suite(suite, name='test', verbose=False, pattern=".*"):
301
return _MyResult(self.stream, self.descriptions, self.verbosity)
304
def run_suite(suite, name='test', verbose=False):
155
from bzrlib.selftest import TestCaseInTempDir
156
TestCaseInTempDir._TEST_NAME = name
306
FunctionalTestCase._TEST_NAME = name