15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
# TODO: Perhaps there should be an API to find out if bzr running under the
19
# test suite -- some plugins might want to avoid making intrusive changes if
20
# this is the case. However, we want behaviour under to test to diverge as
21
# little as possible, so this should be used rarely if it's added at all.
22
# (Suggestion from j-a-meinel, 2005-11-24)
24
# NOTE: Some classes in here use camelCaseNaming() rather than
25
# underscore_naming(). That's for consistency with unittest; it's not the
26
# general style of bzrlib. Please continue that consistency when adding e.g.
27
# new assertFoo() methods.
30
18
from cStringIO import StringIO
44
import bzrlib.bzrdir as bzrdir
45
30
import bzrlib.commands
46
import bzrlib.errors as errors
47
import bzrlib.inventory
48
import bzrlib.iterablefile
50
from bzrlib.merge import merge_inner
53
33
import bzrlib.osutils as osutils
55
import bzrlib.progress as progress
56
from bzrlib.revision import common_ancestor
59
from bzrlib.transport import urlescape, get_transport
60
import bzrlib.transport
61
from bzrlib.transport.local import LocalRelpathServer
62
from bzrlib.transport.readonly import ReadonlyServer
63
from bzrlib.trace import mutter
64
from bzrlib.tests.TestUtil import TestLoader, TestSuite
65
from bzrlib.tests.treeshape import build_tree_contents
66
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
34
from bzrlib.selftest import TestUtil
35
from bzrlib.selftest.TestUtil import TestLoader, TestSuite
68
default_transport = LocalRelpathServer
70
38
MODULES_TO_TEST = []
71
MODULES_TO_DOCTEST = [
83
def packages_to_test():
84
"""Return a list of packages to test.
86
The packages are not globally imported so that import failures are
87
triggered when running selftest, not when importing the command.
90
import bzrlib.tests.blackbox
91
import bzrlib.tests.branch_implementations
92
import bzrlib.tests.bzrdir_implementations
93
import bzrlib.tests.interrepository_implementations
94
import bzrlib.tests.interversionedfile_implementations
95
import bzrlib.tests.repository_implementations
96
import bzrlib.tests.revisionstore_implementations
97
import bzrlib.tests.workingtree_implementations
100
bzrlib.tests.blackbox,
101
bzrlib.tests.branch_implementations,
102
bzrlib.tests.bzrdir_implementations,
103
bzrlib.tests.interrepository_implementations,
104
bzrlib.tests.interversionedfile_implementations,
105
bzrlib.tests.repository_implementations,
106
bzrlib.tests.revisionstore_implementations,
107
bzrlib.tests.workingtree_implementations,
39
MODULES_TO_DOCTEST = []
41
from logging import debug, warning, error
45
class EarlyStoppingTestResultAdapter(object):
46
"""An adapter for TestResult to stop at the first first failure or error"""
48
def __init__(self, result):
51
def addError(self, test, err):
52
self._result.addError(test, err)
55
def addFailure(self, test, err):
56
self._result.addFailure(test, err)
59
def __getattr__(self, name):
60
return getattr(self._result, name)
62
def __setattr__(self, name, value):
64
object.__setattr__(self, name, value)
65
return setattr(self._result, name, value)
111
68
class _MyResult(unittest._TextTestResult):
112
"""Custom TestResult.
114
Shows output in a different format, including displaying runtime for tests.
72
No special behaviour for now.
118
def __init__(self, stream, descriptions, verbosity, pb=None):
119
unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
122
75
def _elapsedTime(self):
123
return "%5dms" % (1000 * (time.time() - self._start_time))
125
def _ellipsise_unimportant_words(self, a_string, final_width,
127
"""Add ellipsese (sp?) for overly long strings.
129
:param keep_start: If true preserve the start of a_string rather
133
if len(a_string) > final_width:
134
result = a_string[:final_width-3] + '...'
138
if len(a_string) > final_width:
139
result = '...' + a_string[3-final_width:]
142
return result.ljust(final_width)
76
return "(Took %.3fs)" % (time.time() - self._start_time)
144
78
def startTest(self, test):
145
79
unittest.TestResult.startTest(self, test)
146
# In a short description, the important words are in
147
# the beginning, but in an id, the important words are
149
SHOW_DESCRIPTIONS = False
151
if not self.showAll and self.dots and self.pb is not None:
154
final_width = osutils.terminal_width()
155
final_width = final_width - 15
157
if SHOW_DESCRIPTIONS:
158
what = test.shortDescription()
160
what = self._ellipsise_unimportant_words(what, final_width, keep_start=True)
163
if what.startswith('bzrlib.tests.'):
165
what = self._ellipsise_unimportant_words(what, final_width)
80
# TODO: Maybe show test.shortDescription somewhere?
81
what = test.shortDescription() or test.id()
167
self.stream.write(what)
168
elif self.dots and self.pb is not None:
169
self.pb.update(what, self.testsRun - 1, None)
83
self.stream.write('%-70.70s' % what)
170
84
self.stream.flush()
171
85
self._start_time = time.time()
173
87
def addError(self, test, err):
174
if isinstance(err[1], TestSkipped):
175
return self.addSkipped(test, err)
176
88
unittest.TestResult.addError(self, test, err)
178
90
self.stream.writeln("ERROR %s" % self._elapsedTime())
179
elif self.dots and self.pb is None:
180
92
self.stream.write('E')
182
self.pb.update(self._ellipsise_unimportant_words('ERROR', 13), self.testsRun, None)
183
93
self.stream.flush()
187
95
def addFailure(self, test, err):
188
96
unittest.TestResult.addFailure(self, test, err)
190
self.stream.writeln(" FAIL %s" % self._elapsedTime())
191
elif self.dots and self.pb is None:
98
self.stream.writeln("FAIL %s" % self._elapsedTime())
192
100
self.stream.write('F')
194
self.pb.update(self._ellipsise_unimportant_words('FAIL', 13), self.testsRun, None)
195
101
self.stream.flush()
199
103
def addSuccess(self, test):
201
self.stream.writeln(' OK %s' % self._elapsedTime())
202
elif self.dots and self.pb is None:
105
self.stream.writeln('OK %s' % self._elapsedTime())
203
107
self.stream.write('~')
205
self.pb.update(self._ellipsise_unimportant_words('OK', 13), self.testsRun, None)
207
unittest.TestResult.addSuccess(self, test)
209
def addSkipped(self, test, skip_excinfo):
211
print >>self.stream, ' SKIP %s' % self._elapsedTime()
212
print >>self.stream, ' %s' % skip_excinfo[1]
213
elif self.dots and self.pb is None:
214
self.stream.write('S')
216
self.pb.update(self._ellipsise_unimportant_words('SKIP', 13), self.testsRun, None)
218
# seems best to treat this as success from point-of-view of unittest
219
# -- it actually does nothing so it barely matters :)
220
109
unittest.TestResult.addSuccess(self, test)
222
111
def printErrorList(self, flavour, errors):
223
112
for test, err in errors:
224
113
self.stream.writeln(self.separator1)
225
self.stream.writeln("%s: %s" % (flavour, self.getDescription(test)))
226
if getattr(test, '_get_log', None) is not None:
228
print >>self.stream, \
229
('vvvv[log from %s]' % test.id()).ljust(78,'-')
114
self.stream.writeln("%s: %s" % (flavour,self.getDescription(test)))
115
if hasattr(test, '_get_log'):
116
self.stream.writeln()
117
self.stream.writeln('log from this test:')
230
118
print >>self.stream, test._get_log()
231
print >>self.stream, \
232
('^^^^[log from %s]' % test.id()).ljust(78,'-')
233
119
self.stream.writeln(self.separator2)
234
120
self.stream.writeln("%s" % err)
237
class TextTestRunner(object):
238
stop_on_failure = False
246
self.stream = unittest._WritelnDecorator(stream)
247
self.descriptions = descriptions
248
self.verbosity = verbosity
249
self.keep_output = keep_output
123
class TextTestRunner(unittest.TextTestRunner):
252
125
def _makeResult(self):
253
result = _MyResult(self.stream,
257
result.stop_early = self.stop_on_failure
261
"Run the given test case or test suite."
262
result = self._makeResult()
263
startTime = time.time()
264
if self.pb is not None:
265
self.pb.update('Running tests', 0, test.countTestCases())
267
stopTime = time.time()
268
timeTaken = stopTime - startTime
270
self.stream.writeln(result.separator2)
271
run = result.testsRun
272
self.stream.writeln("Ran %d test%s in %.3fs" %
273
(run, run != 1 and "s" or "", timeTaken))
274
self.stream.writeln()
275
if not result.wasSuccessful():
276
self.stream.write("FAILED (")
277
failed, errored = map(len, (result.failures, result.errors))
279
self.stream.write("failures=%d" % failed)
281
if failed: self.stream.write(", ")
282
self.stream.write("errors=%d" % errored)
283
self.stream.writeln(")")
285
self.stream.writeln("OK")
286
if self.pb is not None:
287
self.pb.update('Cleaning up', 0, 1)
288
# This is still a little bogus,
289
# but only a little. Folk not using our testrunner will
290
# have to delete their temp directories themselves.
291
test_root = TestCaseInTempDir.TEST_ROOT
292
if result.wasSuccessful() or not self.keep_output:
293
if test_root is not None:
294
osutils.rmtree(test_root)
296
if self.pb is not None:
297
self.pb.note("Failed tests working directories are in '%s'\n",
301
"Failed tests working directories are in '%s'\n" %
303
TestCaseInTempDir.TEST_ROOT = None
304
if self.pb is not None:
126
result = _MyResult(self.stream, self.descriptions, self.verbosity)
127
return EarlyStoppingTestResultAdapter(result)
309
130
def iter_suite_tests(suite):
386
186
# TODO: perhaps override assertEquals to call this for strings?
390
message = "texts not equal:\n"
391
raise AssertionError(message +
189
raise AssertionError("texts not equal:\n" +
392
190
self._ndiff_strings(a, b))
394
def assertEqualMode(self, mode, mode_test):
395
self.assertEqual(mode, mode_test,
396
'mode mismatch %o != %o' % (mode, mode_test))
398
def assertStartsWith(self, s, prefix):
399
if not s.startswith(prefix):
400
raise AssertionError('string %r does not start with %r' % (s, prefix))
402
def assertEndsWith(self, s, suffix):
403
"""Asserts that s ends with suffix."""
404
if not s.endswith(suffix):
405
raise AssertionError('string %r does not end with %r' % (s, suffix))
407
def assertContainsRe(self, haystack, needle_re):
408
"""Assert that a contains something matching a regular expression."""
409
if not re.search(needle_re, haystack):
410
raise AssertionError('pattern "%s" not found in "%s"'
411
% (needle_re, haystack))
413
def assertSubset(self, sublist, superlist):
414
"""Assert that every entry in sublist is present in superlist."""
416
for entry in sublist:
417
if entry not in superlist:
418
missing.append(entry)
420
raise AssertionError("value(s) %r not present in container %r" %
421
(missing, superlist))
423
def assertIs(self, left, right):
424
if not (left is right):
425
raise AssertionError("%r is not %r." % (left, right))
427
def assertTransportMode(self, transport, path, mode):
428
"""Fail if a path does not have mode mode.
430
If modes are not supported on this transport, the assertion is ignored.
432
if not transport._can_roundtrip_unix_modebits():
434
path_stat = transport.stat(path)
435
actual_mode = stat.S_IMODE(path_stat.st_mode)
436
self.assertEqual(mode, actual_mode,
437
'mode of %r incorrect (%o != %o)' % (path, mode, actual_mode))
439
def assertIsInstance(self, obj, kls):
440
"""Fail if obj is not an instance of kls"""
441
if not isinstance(obj, kls):
442
self.fail("%r is an instance of %s rather than %s" % (
443
obj, obj.__class__, kls))
445
def _startLogFile(self):
446
"""Send bzr and test log messages to a temporary file.
448
The file is removed as the test is torn down.
192
def _enable_file_logging(self):
450
193
fileno, name = tempfile.mkstemp(suffix='.log', prefix='testbzr')
451
encoder, decoder, stream_reader, stream_writer = codecs.lookup('UTF-8')
452
self._log_file = stream_writer(os.fdopen(fileno, 'w+'))
453
self._log_nonce = bzrlib.trace.enable_test_log(self._log_file)
195
self._log_file = os.fdopen(fileno, 'w+')
197
hdlr = logging.StreamHandler(self._log_file)
198
hdlr.setLevel(logging.DEBUG)
199
hdlr.setFormatter(logging.Formatter('%(levelname)8s %(message)s'))
200
logging.getLogger('').addHandler(hdlr)
201
logging.getLogger('').setLevel(logging.DEBUG)
202
self._log_hdlr = hdlr
203
debug('opened log file %s', name)
454
205
self._log_file_name = name
455
self.addCleanup(self._finishLogFile)
457
def _finishLogFile(self):
458
"""Finished with the log file.
460
Read contents into memory, close, and delete.
462
bzrlib.trace.disable_test_log(self._log_nonce)
463
self._log_file.seek(0)
464
self._log_contents = self._log_file.read()
208
logging.getLogger('').removeHandler(self._log_hdlr)
209
bzrlib.trace.enable_default_logging()
210
logging.debug('%s teardown', self.id())
465
211
self._log_file.close()
466
os.remove(self._log_file_name)
467
self._log_file = self._log_file_name = None
469
def addCleanup(self, callable):
470
"""Arrange to run a callable when this case is torn down.
472
Callables are run in the reverse of the order they are registered,
473
ie last-in first-out.
475
if callable in self._cleanups:
476
raise ValueError("cleanup function %r already registered on %s"
478
self._cleanups.append(callable)
480
def _cleanEnvironment(self):
483
'APPDATA': os.getcwd(),
488
self.addCleanup(self._restoreEnvironment)
489
for name, value in new_env.iteritems():
490
self._captureVar(name, value)
493
def _captureVar(self, name, newvalue):
494
"""Set an environment variable, preparing it to be reset when finished."""
495
self.__old_env[name] = os.environ.get(name, None)
497
if name in os.environ:
500
os.environ[name] = newvalue
503
def _restoreVar(name, value):
505
if name in os.environ:
508
os.environ[name] = value
510
def _restoreEnvironment(self):
511
for name, value in self.__old_env.iteritems():
512
self._restoreVar(name, value)
516
212
unittest.TestCase.tearDown(self)
518
def _runCleanups(self):
519
"""Run registered cleanup functions.
521
This should only be called from TestCase.tearDown.
523
# TODO: Perhaps this should keep running cleanups even if
525
for cleanup_fn in reversed(self._cleanups):
528
214
def log(self, *args):
531
217
def _get_log(self):
532
218
"""Return as a string the log for this test"""
533
219
if self._log_file_name:
534
220
return open(self._log_file_name).read()
536
return self._log_contents
537
# TODO: Delete the log after it's been read in
539
def capture(self, cmd, retcode=0):
224
def capture(self, cmd):
540
225
"""Shortcut that splits cmd into words, runs, and returns stdout"""
541
return self.run_bzr_captured(cmd.split(), retcode=retcode)[0]
226
return self.run_bzr_captured(cmd.split())[0]
543
def run_bzr_captured(self, argv, retcode=0, stdin=None):
544
"""Invoke bzr and return (stdout, stderr).
228
def run_bzr_captured(self, argv, retcode=0):
229
"""Invoke bzr and return (result, stdout, stderr).
546
231
Useful for code that wants to check the contents of the
547
232
output, the way error messages are presented, etc.
724
380
# successfully created
725
TestCaseInTempDir.TEST_ROOT = osutils.abspath(root)
381
TestCaseInTempDir.TEST_ROOT = os.path.abspath(root)
727
383
# make a fake bzr directory there to prevent any tests propagating
728
384
# up onto the source directory's real branch
729
bzrdir.BzrDir.create_standalone_workingtree(TestCaseInTempDir.TEST_ROOT)
385
os.mkdir(os.path.join(TestCaseInTempDir.TEST_ROOT, '.bzr'))
732
388
super(TestCaseInTempDir, self).setUp()
733
389
self._make_test_root()
734
_currentdir = os.getcwdu()
735
# shorten the name, to avoid test failures due to path length
736
short_id = self.id().replace('bzrlib.tests.', '') \
737
.replace('__main__.', '')[-100:]
738
# it's possible the same test class is run several times for
739
# parameterized tests, so make sure the names don't collide.
743
candidate_dir = '%s/%s.%d' % (self.TEST_ROOT, short_id, i)
745
candidate_dir = '%s/%s' % (self.TEST_ROOT, short_id)
746
if os.path.exists(candidate_dir):
750
self.test_dir = candidate_dir
751
os.mkdir(self.test_dir)
752
os.chdir(self.test_dir)
754
os.environ['HOME'] = self.test_dir
755
os.environ['APPDATA'] = self.test_dir
756
def _leaveDirectory():
757
os.chdir(_currentdir)
758
self.addCleanup(_leaveDirectory)
390
self._currentdir = os.getcwdu()
391
short_id = self.id().replace('bzrlib.selftest.', '') \
392
.replace('__main__.', '')
393
self.test_dir = os.path.join(self.TEST_ROOT, short_id)
394
os.mkdir(self.test_dir)
395
os.chdir(self.test_dir)
760
def build_tree(self, shape, line_endings='native', transport=None):
398
os.chdir(self._currentdir)
399
super(TestCaseInTempDir, self).tearDown()
401
def build_tree(self, shape):
761
402
"""Build a test tree according to a pattern.
763
404
shape is a sequence of file specifications. If the final
764
405
character is '/', a directory is created.
766
407
This doesn't add anything to a branch.
767
:param line_endings: Either 'binary' or 'native'
768
in binary mode, exact contents are written
769
in native mode, the line endings match the
770
default platform endings.
772
:param transport: A transport to write to, for building trees on
773
VFS's. If the transport is readonly or None,
774
"." is opened automatically.
776
409
# XXX: It's OK to just create them using forward slashes on windows?
777
if transport is None or transport.is_readonly():
778
transport = get_transport(".")
779
410
for name in shape:
780
self.assert_(isinstance(name, basestring))
411
assert isinstance(name, basestring)
781
412
if name[-1] == '/':
782
transport.mkdir(urlescape(name[:-1]))
784
if line_endings == 'binary':
786
elif line_endings == 'native':
789
raise errors.BzrError('Invalid line ending request %r' % (line_endings,))
790
content = "contents of %s%s" % (name, end)
791
transport.put(urlescape(name), StringIO(content))
793
def build_tree_contents(self, shape):
794
build_tree_contents(shape)
416
print >>f, "contents of", name
796
419
def failUnlessExists(self, path):
797
420
"""Fail unless path, which may be abs or relative, exists."""
798
421
self.failUnless(osutils.lexists(path))
800
def failIfExists(self, path):
801
"""Fail if path, which may be abs or relative, exists."""
802
self.failIf(osutils.lexists(path))
804
def assertFileEqual(self, content, path):
805
"""Fail if path does not contain 'content'."""
806
self.failUnless(osutils.lexists(path))
807
self.assertEqualDiff(content, open(path, 'r').read())
810
class TestCaseWithTransport(TestCaseInTempDir):
811
"""A test case that provides get_url and get_readonly_url facilities.
813
These back onto two transport servers, one for readonly access and one for
816
If no explicit class is provided for readonly access, a
817
ReadonlyTransportDecorator is used instead which allows the use of non disk
818
based read write transports.
820
If an explicit class is provided for readonly access, that server and the
821
readwrite one must both define get_url() as resolving to os.getcwd().
824
def __init__(self, methodName='testMethod'):
825
super(TestCaseWithTransport, self).__init__(methodName)
826
self.__readonly_server = None
828
self.transport_server = default_transport
829
self.transport_readonly_server = None
831
def get_readonly_url(self, relpath=None):
832
"""Get a URL for the readonly transport.
834
This will either be backed by '.' or a decorator to the transport
835
used by self.get_url()
836
relpath provides for clients to get a path relative to the base url.
837
These should only be downwards relative, not upwards.
839
base = self.get_readonly_server().get_url()
840
if relpath is not None:
841
if not base.endswith('/'):
843
base = base + relpath
846
def get_readonly_server(self):
847
"""Get the server instance for the readonly transport
849
This is useful for some tests with specific servers to do diagnostics.
851
if self.__readonly_server is None:
852
if self.transport_readonly_server is None:
853
# readonly decorator requested
854
# bring up the server
856
self.__readonly_server = ReadonlyServer()
857
self.__readonly_server.setUp(self.__server)
859
self.__readonly_server = self.transport_readonly_server()
860
self.__readonly_server.setUp()
861
self.addCleanup(self.__readonly_server.tearDown)
862
return self.__readonly_server
864
def get_server(self):
865
"""Get the read/write server instance.
867
This is useful for some tests with specific servers that need
870
if self.__server is None:
871
self.__server = self.transport_server()
872
self.__server.setUp()
873
self.addCleanup(self.__server.tearDown)
876
def get_url(self, relpath=None):
877
"""Get a URL for the readwrite transport.
879
This will either be backed by '.' or to an equivalent non-file based
881
relpath provides for clients to get a path relative to the base url.
882
These should only be downwards relative, not upwards.
884
base = self.get_server().get_url()
885
if relpath is not None and relpath != '.':
886
if not base.endswith('/'):
888
base = base + relpath
891
def get_transport(self):
892
"""Return a writeable transport for the test scratch space"""
893
t = get_transport(self.get_url())
894
self.assertFalse(t.is_readonly())
897
def get_readonly_transport(self):
898
"""Return a readonly transport for the test scratch space
900
This can be used to test that operations which should only need
901
readonly access in fact do not try to write.
903
t = get_transport(self.get_readonly_url())
904
self.assertTrue(t.is_readonly())
907
def make_branch(self, relpath, format=None):
908
"""Create a branch on the transport at relpath."""
909
repo = self.make_repository(relpath, format=format)
910
return repo.bzrdir.create_branch()
912
def make_bzrdir(self, relpath, format=None):
914
url = self.get_url(relpath)
915
segments = relpath.split('/')
916
if segments and segments[-1] not in ('', '.'):
917
parent = self.get_url('/'.join(segments[:-1]))
918
t = get_transport(parent)
920
t.mkdir(segments[-1])
921
except errors.FileExists:
924
format=bzrlib.bzrdir.BzrDirFormat.get_default_format()
925
# FIXME: make this use a single transport someday. RBC 20060418
926
return format.initialize_on_transport(get_transport(relpath))
927
except errors.UninitializableFormat:
928
raise TestSkipped("Format %s is not initializable." % format)
930
def make_repository(self, relpath, shared=False, format=None):
931
"""Create a repository on our default transport at relpath."""
932
made_control = self.make_bzrdir(relpath, format=format)
933
return made_control.create_repository(shared=shared)
935
def make_branch_and_tree(self, relpath, format=None):
936
"""Create a branch on the transport and a tree locally.
940
# TODO: always use the local disk path for the working tree,
941
# this obviously requires a format that supports branch references
942
# so check for that by checking bzrdir.BzrDirFormat.get_default_format()
944
b = self.make_branch(relpath, format=format)
946
return b.bzrdir.create_workingtree()
947
except errors.NotLocalUrl:
948
# new formats - catch No tree error and create
949
# a branch reference and a checkout.
950
# old formats at that point - raise TestSkipped.
952
return WorkingTreeFormat2().initialize(bzrdir.BzrDir.open(relpath))
954
def assertIsDirectory(self, relpath, transport):
955
"""Assert that relpath within transport is a directory.
957
This may not be possible on all transports; in that case it propagates
958
a TransportNotPossible.
961
mode = transport.stat(relpath).st_mode
962
except errors.NoSuchFile:
963
self.fail("path %s is not a directory; no such file"
965
if not stat.S_ISDIR(mode):
966
self.fail("path %s is not a directory; has mode %#o"
970
class ChrootedTestCase(TestCaseWithTransport):
971
"""A support class that provides readonly urls outside the local namespace.
973
This is done by checking if self.transport_server is a MemoryServer. if it
974
is then we are chrooted already, if it is not then an HttpServer is used
977
TODO RBC 20060127: make this an option to TestCaseWithTransport so it can
978
be used without needed to redo it when a different
983
super(ChrootedTestCase, self).setUp()
984
if not self.transport_server == bzrlib.transport.memory.MemoryServer:
985
self.transport_readonly_server = bzrlib.transport.http.HttpServer
424
class MetaTestLog(TestCase):
425
def test_logging(self):
426
"""Test logs are captured when a test fails."""
427
logging.info('an info message')
428
warning('something looks dodgy...')
429
logging.debug('hello, test is running')
988
433
def filter_suite_by_re(suite, pattern):
434
result = TestUtil.TestSuite()
990
435
filter_re = re.compile(pattern)
991
436
for test in iter_suite_tests(suite):
992
437
if filter_re.search(test.id()):
997
def run_suite(suite, name='test', verbose=False, pattern=".*",
998
stop_on_failure=False, keep_output=False,
442
def run_suite(suite, name='test', verbose=False, pattern=".*"):
1000
443
TestCaseInTempDir._TEST_NAME = name
1006
pb = progress.ProgressBar()
1007
448
runner = TextTestRunner(stream=sys.stdout,
1009
verbosity=verbosity,
1010
keep_output=keep_output,
1012
runner.stop_on_failure=stop_on_failure
1013
451
if pattern != '.*':
1014
452
suite = filter_suite_by_re(suite, pattern)
1015
453
result = runner.run(suite)
454
# This is still a little bogus,
455
# but only a little. Folk not using our testrunner will
456
# have to delete their temp directories themselves.
457
if result.wasSuccessful():
458
if TestCaseInTempDir.TEST_ROOT is not None:
459
shutil.rmtree(TestCaseInTempDir.TEST_ROOT)
461
print "Failed tests working directories are in '%s'\n" % TestCaseInTempDir.TEST_ROOT
1016
462
return result.wasSuccessful()
1019
def selftest(verbose=False, pattern=".*", stop_on_failure=True,
465
def selftest(verbose=False, pattern=".*"):
1022
466
"""Run the whole test suite under the enhanced runner"""
1023
global default_transport
1024
if transport is None:
1025
transport = default_transport
1026
old_transport = default_transport
1027
default_transport = transport
1028
suite = test_suite()
1030
return run_suite(suite, 'testbzr', verbose=verbose, pattern=pattern,
1031
stop_on_failure=stop_on_failure, keep_output=keep_output,
1032
transport=transport)
1034
default_transport = old_transport
467
return run_suite(test_suite(), 'testbzr', verbose=verbose, pattern=pattern)
1038
470
def test_suite():
1039
471
"""Build and return TestSuite for the whole program."""
472
import bzrlib.store, bzrlib.inventory, bzrlib.branch
473
import bzrlib.osutils, bzrlib.merge3, bzrlib.plugin
1040
474
from doctest import DocTestSuite
1042
global MODULES_TO_DOCTEST
476
global MODULES_TO_TEST, MODULES_TO_DOCTEST
1045
'bzrlib.tests.test_ancestry',
1046
'bzrlib.tests.test_api',
1047
'bzrlib.tests.test_bad_files',
1048
'bzrlib.tests.test_branch',
1049
'bzrlib.tests.test_bzrdir',
1050
'bzrlib.tests.test_command',
1051
'bzrlib.tests.test_commit',
1052
'bzrlib.tests.test_commit_merge',
1053
'bzrlib.tests.test_config',
1054
'bzrlib.tests.test_conflicts',
1055
'bzrlib.tests.test_decorators',
1056
'bzrlib.tests.test_diff',
1057
'bzrlib.tests.test_doc_generate',
1058
'bzrlib.tests.test_errors',
1059
'bzrlib.tests.test_escaped_store',
1060
'bzrlib.tests.test_fetch',
1061
'bzrlib.tests.test_gpg',
1062
'bzrlib.tests.test_graph',
1063
'bzrlib.tests.test_hashcache',
1064
'bzrlib.tests.test_http',
1065
'bzrlib.tests.test_identitymap',
1066
'bzrlib.tests.test_inv',
1067
'bzrlib.tests.test_knit',
1068
'bzrlib.tests.test_lockdir',
1069
'bzrlib.tests.test_lockable_files',
1070
'bzrlib.tests.test_log',
1071
'bzrlib.tests.test_merge',
1072
'bzrlib.tests.test_merge3',
1073
'bzrlib.tests.test_merge_core',
1074
'bzrlib.tests.test_missing',
1075
'bzrlib.tests.test_msgeditor',
1076
'bzrlib.tests.test_nonascii',
1077
'bzrlib.tests.test_options',
1078
'bzrlib.tests.test_osutils',
1079
'bzrlib.tests.test_patch',
1080
'bzrlib.tests.test_permissions',
1081
'bzrlib.tests.test_plugins',
1082
'bzrlib.tests.test_progress',
1083
'bzrlib.tests.test_reconcile',
1084
'bzrlib.tests.test_repository',
1085
'bzrlib.tests.test_revision',
1086
'bzrlib.tests.test_revisionnamespaces',
1087
'bzrlib.tests.test_revprops',
1088
'bzrlib.tests.test_rio',
1089
'bzrlib.tests.test_sampler',
1090
'bzrlib.tests.test_selftest',
1091
'bzrlib.tests.test_setup',
1092
'bzrlib.tests.test_sftp_transport',
1093
'bzrlib.tests.test_smart_add',
1094
'bzrlib.tests.test_source',
1095
'bzrlib.tests.test_status',
1096
'bzrlib.tests.test_store',
1097
'bzrlib.tests.test_symbol_versioning',
1098
'bzrlib.tests.test_testament',
1099
'bzrlib.tests.test_textfile',
1100
'bzrlib.tests.test_textmerge',
1101
'bzrlib.tests.test_trace',
1102
'bzrlib.tests.test_transactions',
1103
'bzrlib.tests.test_transform',
1104
'bzrlib.tests.test_transport',
1105
'bzrlib.tests.test_tsort',
1106
'bzrlib.tests.test_tuned_gzip',
1107
'bzrlib.tests.test_ui',
1108
'bzrlib.tests.test_upgrade',
1109
'bzrlib.tests.test_versionedfile',
1110
'bzrlib.tests.test_weave',
1111
'bzrlib.tests.test_whitebox',
1112
'bzrlib.tests.test_workingtree',
1113
'bzrlib.tests.test_xml',
479
['bzrlib.selftest.MetaTestLog',
480
'bzrlib.selftest.testidentitymap',
481
'bzrlib.selftest.testinv',
482
'bzrlib.selftest.test_ancestry',
483
'bzrlib.selftest.test_commit',
484
'bzrlib.selftest.test_commit_merge',
485
'bzrlib.selftest.testconfig',
486
'bzrlib.selftest.versioning',
487
'bzrlib.selftest.testmerge3',
488
'bzrlib.selftest.testmerge',
489
'bzrlib.selftest.testhashcache',
490
'bzrlib.selftest.teststatus',
491
'bzrlib.selftest.testlog',
492
'bzrlib.selftest.testrevisionnamespaces',
493
'bzrlib.selftest.testbranch',
494
'bzrlib.selftest.testrevision',
495
'bzrlib.selftest.test_revision_info',
496
'bzrlib.selftest.test_merge_core',
497
'bzrlib.selftest.test_smart_add',
498
'bzrlib.selftest.test_bad_files',
499
'bzrlib.selftest.testdiff',
500
'bzrlib.selftest.test_parent',
501
'bzrlib.selftest.test_xml',
502
'bzrlib.selftest.test_weave',
503
'bzrlib.selftest.testfetch',
504
'bzrlib.selftest.whitebox',
505
'bzrlib.selftest.teststore',
506
'bzrlib.selftest.blackbox',
507
'bzrlib.selftest.testsampler',
508
'bzrlib.selftest.testtransactions',
509
'bzrlib.selftest.testtransport',
510
'bzrlib.selftest.testgraph',
511
'bzrlib.selftest.testworkingtree',
512
'bzrlib.selftest.test_upgrade',
513
'bzrlib.selftest.test_conflicts',
514
'bzrlib.selftest.testtestament',
515
'bzrlib.selftest.testannotate',
516
'bzrlib.selftest.testrevprops',
1115
test_transport_implementations = [
1116
'bzrlib.tests.test_transport_implementations']
1118
TestCase.BZRPATH = osutils.pathjoin(
1119
osutils.realpath(osutils.dirname(bzrlib.__path__[0])), 'bzr')
1120
print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
1121
print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
519
for m in (bzrlib.store, bzrlib.inventory, bzrlib.branch,
520
bzrlib.osutils, bzrlib.commands, bzrlib.merge3):
521
if m not in MODULES_TO_DOCTEST:
522
MODULES_TO_DOCTEST.append(m)
524
TestCase.BZRPATH = os.path.join(os.path.realpath(os.path.dirname(bzrlib.__path__[0])), 'bzr')
525
print '%-30s %s' % ('bzr binary', TestCase.BZRPATH)
1123
527
suite = TestSuite()
1124
# python2.4's TestLoader.loadTestsFromNames gives very poor
1125
# errors if it fails to load a named module - no indication of what's
1126
# actually wrong, just "no such module". We should probably override that
1127
# class, but for the moment just load them ourselves. (mbp 20051202)
1128
loader = TestLoader()
1129
from bzrlib.transport import TransportTestProviderAdapter
1130
adapter = TransportTestProviderAdapter()
1131
adapt_modules(test_transport_implementations, adapter, loader, suite)
1132
for mod_name in testmod_names:
1133
mod = _load_module_by_name(mod_name)
1134
suite.addTest(loader.loadTestsFromModule(mod))
1135
for package in packages_to_test():
1136
suite.addTest(package.test_suite())
528
suite.addTest(TestLoader().loadTestsFromNames(testmod_names))
1137
529
for m in MODULES_TO_TEST:
1138
suite.addTest(loader.loadTestsFromModule(m))
530
suite.addTest(TestLoader().loadTestsFromModule(m))
1139
531
for m in (MODULES_TO_DOCTEST):
1140
532
suite.addTest(DocTestSuite(m))
1141
for name, plugin in bzrlib.plugin.all_plugins().items():
1142
if getattr(plugin, 'test_suite', None) is not None:
1143
suite.addTest(plugin.test_suite())
533
for p in bzrlib.plugin.all_plugins:
534
if hasattr(p, 'test_suite'):
535
suite.addTest(p.test_suite())
1147
def adapt_modules(mods_list, adapter, loader, suite):
1148
"""Adapt the modules in mods_list using adapter and add to suite."""
1149
for mod_name in mods_list:
1150
mod = _load_module_by_name(mod_name)
1151
for test in iter_suite_tests(loader.loadTestsFromModule(mod)):
1152
suite.addTests(adapter.adapt(test))
1155
def _load_module_by_name(mod_name):
1156
parts = mod_name.split('.')
1157
module = __import__(mod_name)
1159
# for historical reasons python returns the top-level module even though
1160
# it loads the submodule; we need to walk down to get the one we want.
1162
module = getattr(module, parts.pop(0))