15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
from unittest import TestResult, TestCase
20
class CommandFailed(Exception):
24
class TestBase(TestCase):
25
"""Base class for bzr test cases.
27
Just defines some useful helper functions; doesn't actually test
31
# TODO: Special methods to invoke bzr, so that we can run it
32
# through a specified Python intepreter
34
OVERRIDE_PYTHON = None # to run with alternative python 'python'
40
def formcmd(self, cmd):
41
if isinstance(cmd, basestring):
46
if self.OVERRIDE_PYTHON:
47
cmd.insert(0, self.OVERRIDE_PYTHON)
49
self.log('$ %r' % cmd)
54
def runcmd(self, cmd, retcode=0):
55
"""Run one command and check the return code.
57
Returns a tuple of (stdout,stderr) strings.
59
If a single string is based, it is split into words.
60
For commands that are not simple space-separated words, please
61
pass a list instead."""
64
from subprocess import call
65
except ImportError, e:
67
sys.stderr.write("testbzr: sorry, this test suite requires the subprocess module\n"
68
"this is shipped with python2.4 and available separately for 2.3\n")
72
cmd = self.formcmd(cmd)
74
self.log('$ ' + ' '.join(cmd))
75
actual_retcode = call(cmd, stdout=self.TEST_LOG, stderr=self.TEST_LOG)
77
if retcode != actual_retcode:
78
raise CommandFailed("test failed: %r returned %d, expected %d"
79
% (cmd, actual_retcode, retcode))
82
def backtick(self, cmd, retcode=0):
83
"""Run a command and return its output"""
86
from subprocess import Popen, PIPE
87
except ImportError, e:
89
sys.stderr.write("testbzr: sorry, this test suite requires the subprocess module\n"
90
"this is shipped with python2.4 and available separately for 2.3\n")
94
cmd = self.formcmd(cmd)
95
child = Popen(cmd, stdout=PIPE, stderr=self.TEST_LOG)
96
outd, errd = child.communicate()
98
actual_retcode = child.wait()
100
outd = outd.replace('\r', '')
102
if retcode != actual_retcode:
103
raise CommandFailed("test failed: %r returned %d, expected %d"
104
% (cmd, actual_retcode, retcode))
110
def build_tree(self, shape):
111
"""Build a test tree according to a pattern.
113
shape is a sequence of file specifications. If the final
114
character is '/', a directory is created.
116
This doesn't add anything to a branch.
118
# XXX: It's OK to just create them using forward slashes on windows?
121
assert isinstance(name, basestring)
126
print >>f, "contents of", name
131
"""Log a message to a progress file"""
132
self._log_buf = self._log_buf + str(msg) + '\n'
133
print >>self.TEST_LOG, msg
136
def check_inventory_shape(self, inv, shape):
138
Compare an inventory to a list of expected names.
140
Fail if they are not precisely equal.
143
shape = list(shape) # copy
144
for path, ie in inv.entries():
145
name = path.replace('\\', '/')
153
self.fail("expected paths not found in inventory: %r" % shape)
155
self.fail("unexpected paths found in inventory: %r" % extras)
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" % expected)
163
self.log("actually: %r" % contents)
164
self.fail("contents of %s not as expected")
168
class InTempDir(TestBase):
169
"""Base class for tests run in a temporary branch."""
172
self.test_dir = os.path.join(self.TEST_ROOT, self.__class__.__name__)
173
os.mkdir(self.test_dir)
174
os.chdir(self.test_dir)
178
os.chdir(self.TEST_ROOT)
184
class _MyResult(TestResult):
188
No special behaviour for now.
190
def __init__(self, out):
192
TestResult.__init__(self)
194
def startTest(self, test):
195
# TODO: Maybe show test.shortDescription somewhere?
196
print >>self.out, '%-60.60s' % test.id(),
198
TestResult.startTest(self, test)
200
def stopTest(self, test):
202
TestResult.stopTest(self, test)
205
def addError(self, test, err):
206
print >>self.out, 'ERROR'
207
TestResult.addError(self, test, err)
208
_show_test_failure('error', test, err, self.out)
210
def addFailure(self, test, err):
211
print >>self.out, 'FAILURE'
212
TestResult.addFailure(self, test, err)
213
_show_test_failure('failure', test, err, self.out)
215
def addSuccess(self, test):
216
print >>self.out, 'OK'
217
TestResult.addSuccess(self, test)
18
from testsweet import TestBase, run_suite, InTempDir
259
57
suite.addTest(bzrlib.selftest.blackbox.suite())
261
# save stdout & stderr so there's no leakage from code-under-test
262
real_stdout = sys.stdout
263
real_stderr = sys.stderr
264
sys.stdout = sys.stderr = TestBase.TEST_LOG
266
result = _MyResult(real_stdout)
269
sys.stdout = real_stdout
270
sys.stderr = real_stderr
272
_show_results(result)
274
return result.wasSuccessful()
279
def _setup_test_log():
283
log_filename = os.path.abspath('testbzr.log')
284
TestBase.TEST_LOG = open(log_filename, 'wt', buffering=1) # line buffered
286
print >>TestBase.TEST_LOG, "bzr tests run at " + time.ctime()
287
print '%-30s %s' % ('test log', log_filename)
290
def _setup_test_dir():
294
TestBase.ORIG_DIR = os.getcwdu()
295
TestBase.TEST_ROOT = os.path.abspath("testbzr.tmp")
297
print '%-30s %s' % ('running tests in', TestBase.TEST_ROOT)
299
if os.path.exists(TestBase.TEST_ROOT):
300
shutil.rmtree(TestBase.TEST_ROOT)
301
os.mkdir(TestBase.TEST_ROOT)
302
os.chdir(TestBase.TEST_ROOT)
304
# make a fake bzr directory there to prevent any tests propagating
305
# up onto the source directory's real branch
306
os.mkdir(os.path.join(TestBase.TEST_ROOT, '.bzr'))
310
def _show_results(result):
312
print '%4d tests run' % result.testsRun
313
print '%4d errors' % len(result.errors)
314
print '%4d failures' % len(result.failures)
318
def _show_test_failure(kind, case, exc_info, out):
319
from traceback import print_exception
321
print >>out, '-' * 60
324
desc = case.shortDescription()
326
print >>out, ' (%s)' % desc
328
print_exception(exc_info[0], exc_info[1], exc_info[2], None, out)
330
if isinstance(case, TestBase):
332
print >>out, 'log from this test:'
333
print >>out, case._log_buf
335
print >>out, '-' * 60
59
return run_suite(suite)