56
56
# XXX: Not used yet
59
class TestCase(unittest.TestCase):
60
"""Base class for bzr unit tests.
62
Tests that need access to disk resources should subclass
63
FunctionalTestCase not TestCase.
66
# TODO: Special methods to invoke bzr, so that we can run it
67
# through a specified Python intepreter
69
OVERRIDE_PYTHON = None # to run with alternative python 'python'
72
def apply_redirected(self, stdin=None, stdout=None, stderr=None,
73
a_callable=None, *args, **kwargs):
74
"""Call callable with redirected std io pipes.
76
Returns the return code."""
77
from StringIO import StringIO
78
if not callable(a_callable):
79
raise ValueError("a_callable must be callable.")
83
stdout = self.TEST_LOG
85
stderr = self.TEST_LOG
86
real_stdin = sys.stdin
87
real_stdout = sys.stdout
88
real_stderr = sys.stderr
94
result = a_callable(*args, **kwargs)
96
sys.stdout = real_stdout
97
sys.stderr = real_stderr
98
sys.stdin = real_stdin
102
super(TestCase, self).setUp()
103
# setup a temporary log for the test
105
self.TEST_LOG = tempfile.NamedTemporaryFile(mode='wt', bufsize=0)
106
self.log("%s setup" % self.id())
109
self.log("%s teardown" % self.id())
111
super(TestCase, self).tearDown()
114
"""Log a message to a progress file"""
115
print >>self.TEST_LOG, msg
117
def check_inventory_shape(self, inv, shape):
119
Compare an inventory to a list of expected names.
121
Fail if they are not precisely equal.
124
shape = list(shape) # copy
125
for path, ie in inv.entries():
126
name = path.replace('\\', '/')
134
self.fail("expected paths not found in inventory: %r" % shape)
136
self.fail("unexpected paths found in inventory: %r" % extras)
139
"""Get the log the test case used. This can only be called once,
140
after which an exception will be raised.
142
self.TEST_LOG.flush()
143
log = open(self.TEST_LOG.name, 'rt').read()
144
self.TEST_LOG.close()
148
class FunctionalTestCase(TestCase):
149
"""Base class for tests that perform function testing - running bzr,
150
using files on disk, and similar activities.
152
InTempDir is an old alias for FunctionalTestCase.
158
def check_file_contents(self, filename, expect):
159
self.log("check contents of file %s" % filename)
160
contents = file(filename, 'r').read()
161
if contents != expect:
162
self.log("expected: %r" % expect)
163
self.log("actually: %r" % contents)
164
self.fail("contents of %s not as expected")
166
def _make_test_root(self):
171
if FunctionalTestCase.TEST_ROOT is not None:
173
FunctionalTestCase.TEST_ROOT = os.path.abspath(
174
tempfile.mkdtemp(suffix='.tmp',
175
prefix=self._TEST_NAME + '-',
178
# make a fake bzr directory there to prevent any tests propagating
179
# up onto the source directory's real branch
180
os.mkdir(os.path.join(FunctionalTestCase.TEST_ROOT, '.bzr'))
183
super(FunctionalTestCase, self).setUp()
185
self._make_test_root()
186
self._currentdir = os.getcwdu()
187
self.test_dir = os.path.join(self.TEST_ROOT, self.id())
188
os.mkdir(self.test_dir)
189
os.chdir(self.test_dir)
193
os.chdir(self._currentdir)
194
super(FunctionalTestCase, self).tearDown()
196
def formcmd(self, cmd):
197
if isinstance(cmd, basestring):
200
cmd[0] = self.BZRPATH
201
if self.OVERRIDE_PYTHON:
202
cmd.insert(0, self.OVERRIDE_PYTHON)
203
self.log('$ %r' % cmd)
206
def runcmd(self, cmd, retcode=0):
207
"""Run one command and check the return code.
209
Returns a tuple of (stdout,stderr) strings.
211
If a single string is based, it is split into words.
212
For commands that are not simple space-separated words, please
213
pass a list instead."""
216
from subprocess import call
217
except ImportError, e:
220
cmd = self.formcmd(cmd)
221
self.log('$ ' + ' '.join(cmd))
222
actual_retcode = call(cmd, stdout=self.TEST_LOG, stderr=self.TEST_LOG)
223
if retcode != actual_retcode:
224
raise CommandFailed("test failed: %r returned %d, expected %d"
225
% (cmd, actual_retcode, retcode))
227
def backtick(self, cmd, retcode=0):
228
"""Run a command and return its output"""
231
from subprocess import Popen, PIPE
232
except ImportError, e:
235
cmd = self.formcmd(cmd)
236
child = Popen(cmd, stdout=PIPE, stderr=self.TEST_LOG)
237
outd, errd = child.communicate()
239
actual_retcode = child.wait()
240
outd = outd.replace('\r', '')
241
if retcode != actual_retcode:
242
raise CommandFailed("test failed: %r returned %d, expected %d"
243
% (cmd, actual_retcode, retcode))
246
def build_tree(self, shape):
247
"""Build a test tree according to a pattern.
249
shape is a sequence of file specifications. If the final
250
character is '/', a directory is created.
252
This doesn't add anything to a branch.
254
# XXX: It's OK to just create them using forward slashes on windows?
257
assert isinstance(name, basestring)
262
print >>f, "contents of", name
265
InTempDir = FunctionalTestCase
268
60
class EarlyStoppingTestResultAdapter(object):
269
61
"""An adapter for TestResult to stop at the first first failure or error"""