333
336
def test_scenarios(self):
334
337
# check that constructor parameters are passed through to the adapted
336
from bzrlib.tests.per_workingtree import make_scenarios
339
from .per_workingtree import make_scenarios
339
formats = [workingtree.WorkingTreeFormat2(),
340
workingtree.WorkingTreeFormat3(),]
341
scenarios = make_scenarios(server1, server2, formats)
342
formats = [workingtree_4.WorkingTreeFormat4(),
343
workingtree_3.WorkingTreeFormat3(),
344
workingtree_4.WorkingTreeFormat6()]
345
scenarios = make_scenarios(server1, server2, formats,
346
remote_server='c', remote_readonly_server='d',
347
remote_backing_server='e')
342
348
self.assertEqual([
343
('WorkingTreeFormat2',
344
{'bzrdir_format': formats[0]._matchingbzrdir,
349
('WorkingTreeFormat4',
350
{'bzrdir_format': formats[0]._matchingcontroldir,
345
351
'transport_readonly_server': 'b',
346
352
'transport_server': 'a',
347
353
'workingtree_format': formats[0]}),
348
354
('WorkingTreeFormat3',
349
{'bzrdir_format': formats[1]._matchingbzrdir,
350
'transport_readonly_server': 'b',
351
'transport_server': 'a',
352
'workingtree_format': formats[1]})],
355
{'bzrdir_format': formats[1]._matchingcontroldir,
356
'transport_readonly_server': 'b',
357
'transport_server': 'a',
358
'workingtree_format': formats[1]}),
359
('WorkingTreeFormat6',
360
{'bzrdir_format': formats[2]._matchingcontroldir,
361
'transport_readonly_server': 'b',
362
'transport_server': 'a',
363
'workingtree_format': formats[2]}),
364
('WorkingTreeFormat6,remote',
365
{'bzrdir_format': formats[2]._matchingcontroldir,
366
'repo_is_remote': True,
367
'transport_readonly_server': 'd',
368
'transport_server': 'c',
369
'vfs_transport_factory': 'e',
370
'workingtree_format': formats[2]}),
356
374
class TestTreeScenarios(tests.TestCase):
358
376
def test_scenarios(self):
359
377
# the tree implementation scenario generator is meant to setup one
360
# instance for each working tree format, and one additional instance
378
# instance for each working tree format, one additional instance
361
379
# that will use the default wt format, but create a revision tree for
362
# the tests. this means that the wt ones should have the
363
# workingtree_to_test_tree attribute set to 'return_parameter' and the
364
# revision one set to revision_tree_from_workingtree.
380
# the tests, and one more that uses the default wt format as a
381
# lightweight checkout of a remote repository. This means that the wt
382
# ones should have the workingtree_to_test_tree attribute set to
383
# 'return_parameter' and the revision one set to
384
# revision_tree_from_workingtree.
366
from bzrlib.tests.per_tree import (
386
from .per_tree import (
367
387
_dirstate_tree_from_workingtree,
369
389
preview_tree_pre,
376
formats = [workingtree.WorkingTreeFormat2(),
377
workingtree.WorkingTreeFormat3(),]
396
smart_server = test_server.SmartTCPServer_for_testing
397
smart_readonly_server = test_server.ReadonlySmartTCPServer_for_testing
398
mem_server = memory.MemoryServer
399
formats = [workingtree_4.WorkingTreeFormat4(),
400
workingtree_3.WorkingTreeFormat3(),]
378
401
scenarios = make_scenarios(server1, server2, formats)
379
self.assertEqual(7, len(scenarios))
380
default_wt_format = workingtree.WorkingTreeFormat4._default_format
381
wt4_format = workingtree.WorkingTreeFormat4()
382
wt5_format = workingtree.WorkingTreeFormat5()
402
self.assertEqual(8, len(scenarios))
403
default_wt_format = workingtree.format_registry.get_default()
404
wt4_format = workingtree_4.WorkingTreeFormat4()
405
wt5_format = workingtree_4.WorkingTreeFormat5()
406
wt6_format = workingtree_4.WorkingTreeFormat6()
383
407
expected_scenarios = [
384
('WorkingTreeFormat2',
385
{'bzrdir_format': formats[0]._matchingbzrdir,
408
('WorkingTreeFormat4',
409
{'bzrdir_format': formats[0]._matchingcontroldir,
386
410
'transport_readonly_server': 'b',
387
411
'transport_server': 'a',
388
412
'workingtree_format': formats[0],
389
413
'_workingtree_to_test_tree': return_parameter,
391
415
('WorkingTreeFormat3',
392
{'bzrdir_format': formats[1]._matchingbzrdir,
416
{'bzrdir_format': formats[1]._matchingcontroldir,
393
417
'transport_readonly_server': 'b',
394
418
'transport_server': 'a',
395
419
'workingtree_format': formats[1],
396
420
'_workingtree_to_test_tree': return_parameter,
422
('WorkingTreeFormat6,remote',
423
{'bzrdir_format': wt6_format._matchingcontroldir,
424
'repo_is_remote': True,
425
'transport_readonly_server': smart_readonly_server,
426
'transport_server': smart_server,
427
'vfs_transport_factory': mem_server,
428
'workingtree_format': wt6_format,
429
'_workingtree_to_test_tree': return_parameter,
399
432
{'_workingtree_to_test_tree': revision_tree_from_workingtree,
400
'bzrdir_format': default_wt_format._matchingbzrdir,
433
'bzrdir_format': default_wt_format._matchingcontroldir,
401
434
'transport_readonly_server': 'b',
402
435
'transport_server': 'a',
403
436
'workingtree_format': default_wt_format,
405
438
('DirStateRevisionTree,WT4',
406
439
{'_workingtree_to_test_tree': _dirstate_tree_from_workingtree,
407
'bzrdir_format': wt4_format._matchingbzrdir,
440
'bzrdir_format': wt4_format._matchingcontroldir,
408
441
'transport_readonly_server': 'b',
409
442
'transport_server': 'a',
410
443
'workingtree_format': wt4_format,
412
445
('DirStateRevisionTree,WT5',
413
446
{'_workingtree_to_test_tree': _dirstate_tree_from_workingtree,
414
'bzrdir_format': wt5_format._matchingbzrdir,
447
'bzrdir_format': wt5_format._matchingcontroldir,
415
448
'transport_readonly_server': 'b',
416
449
'transport_server': 'a',
417
450
'workingtree_format': wt5_format,
420
453
{'_workingtree_to_test_tree': preview_tree_pre,
421
'bzrdir_format': default_wt_format._matchingbzrdir,
454
'bzrdir_format': default_wt_format._matchingcontroldir,
422
455
'transport_readonly_server': 'b',
423
456
'transport_server': 'a',
424
457
'workingtree_format': default_wt_format}),
425
458
('PreviewTreePost',
426
459
{'_workingtree_to_test_tree': preview_tree_post,
427
'bzrdir_format': default_wt_format._matchingbzrdir,
460
'bzrdir_format': default_wt_format._matchingcontroldir,
428
461
'transport_readonly_server': 'b',
429
462
'transport_server': 'a',
430
463
'workingtree_format': default_wt_format}),
592
631
the_branch = builder.get_branch()
593
632
# Guard against regression into MemoryTransport leaking
594
633
# files to disk instead of keeping them in memory.
595
self.failIf(osutils.lexists('dir'))
596
dir_format = bzrdir.format_registry.make_bzrdir('knit')
634
self.assertFalse(osutils.lexists('dir'))
635
dir_format = controldir.format_registry.make_controldir('knit')
597
636
self.assertEqual(dir_format.repository_format.__class__,
598
637
the_branch.repository._format.__class__)
599
self.assertEqual('Bazaar-NG Knit Repository Format 1',
638
self.assertEqual(b'Bazaar-NG Knit Repository Format 1',
600
639
self.get_transport().get_bytes(
601
640
'dir/.bzr/repository/format'))
603
642
def test_dangling_locks_cause_failures(self):
604
643
class TestDanglingLock(tests.TestCaseWithMemoryTransport):
605
644
def test_function(self):
606
t = self.get_transport('.')
645
t = self.get_transport_from_path('.')
607
646
l = lockdir.LockDir(t, 'lock')
610
649
test = TestDanglingLock('test_function')
611
650
result = test.run()
651
total_failures = result.errors + result.failures
612
652
if self._lock_check_thorough:
613
self.assertEqual(1, len(result.errors))
653
self.assertEqual(1, len(total_failures))
615
655
# When _lock_check_thorough is disabled, then we don't trigger a
617
self.assertEqual(0, len(result.errors))
657
self.assertEqual(0, len(total_failures))
620
660
class TestTestCaseWithTransport(tests.TestCaseWithTransport):
621
661
"""Tests for the convenience functions TestCaseWithTransport introduces."""
623
663
def test_get_readonly_url_none(self):
624
from bzrlib.transport import get_transport
625
from bzrlib.transport.readonly import ReadonlyTransportDecorator
664
from ..transport.readonly import ReadonlyTransportDecorator
626
665
self.vfs_transport_factory = memory.MemoryServer
627
666
self.transport_readonly_server = None
628
667
# calling get_readonly_transport() constructs a decorator on the url
630
669
url = self.get_readonly_url()
631
670
url2 = self.get_readonly_url('foo/bar')
632
t = get_transport(url)
633
t2 = get_transport(url2)
634
self.failUnless(isinstance(t, ReadonlyTransportDecorator))
635
self.failUnless(isinstance(t2, ReadonlyTransportDecorator))
671
t = transport.get_transport_from_url(url)
672
t2 = transport.get_transport_from_url(url2)
673
self.assertIsInstance(t, ReadonlyTransportDecorator)
674
self.assertIsInstance(t2, ReadonlyTransportDecorator)
636
675
self.assertEqual(t2.base[:-1], t.abspath('foo/bar'))
638
677
def test_get_readonly_url_http(self):
639
from bzrlib.tests.http_server import HttpServer
640
from bzrlib.transport import get_transport
641
from bzrlib.transport.http import HttpTransportBase
678
from .http_server import HttpServer
679
from ..transport.http import HttpTransport
642
680
self.transport_server = test_server.LocalURLServer
643
681
self.transport_readonly_server = HttpServer
644
682
# calling get_readonly_transport() gives us a HTTP server instance.
645
683
url = self.get_readonly_url()
646
684
url2 = self.get_readonly_url('foo/bar')
647
685
# the transport returned may be any HttpTransportBase subclass
648
t = get_transport(url)
649
t2 = get_transport(url2)
650
self.failUnless(isinstance(t, HttpTransportBase))
651
self.failUnless(isinstance(t2, HttpTransportBase))
686
t = transport.get_transport_from_url(url)
687
t2 = transport.get_transport_from_url(url2)
688
self.assertIsInstance(t, HttpTransport)
689
self.assertIsInstance(t2, HttpTransport)
652
690
self.assertEqual(t2.base[:-1], t.abspath('foo/bar'))
654
692
def test_is_directory(self):
743
777
r"^ +[0-9]+ms\*$")
745
779
def test_unittest_reporting_unittest_class(self):
746
# getting the time from a non-bzrlib test works ok
780
# getting the time from a non-breezy test works ok
747
781
class ShortDelayTestCase(unittest.TestCase):
748
782
def test_short_delay(self):
749
783
time.sleep(0.003)
750
784
self.check_timing(ShortDelayTestCase('test_short_delay'),
753
def _patch_get_bzr_source_tree(self):
754
# Reading from the actual source tree breaks isolation, but we don't
755
# want to assume that thats *all* that would happen.
756
self.overrideAttr(bzrlib.version, '_get_bzr_source_tree', lambda: None)
758
def test_assigned_benchmark_file_stores_date(self):
759
self._patch_get_bzr_source_tree()
761
result = bzrlib.tests.TextTestResult(self._log_file,
766
output_string = output.getvalue()
767
# if you are wondering about the regexp please read the comment in
768
# test_bench_history (bzrlib.tests.test_selftest.TestRunner)
769
# XXX: what comment? -- Andrew Bennetts
770
self.assertContainsRe(output_string, "--date [0-9.]+")
772
def test_benchhistory_records_test_times(self):
773
self._patch_get_bzr_source_tree()
774
result_stream = StringIO()
775
result = bzrlib.tests.TextTestResult(
779
bench_history=result_stream
782
# we want profile a call and check that its test duration is recorded
783
# make a new test instance that when run will generate a benchmark
784
example_test_case = TestTestResult("_time_hello_world_encoding")
785
# execute the test, which should succeed and record times
786
example_test_case.run(result)
787
lines = result_stream.getvalue().splitlines()
788
self.assertEqual(2, len(lines))
789
self.assertContainsRe(lines[1],
790
" *[0-9]+ms bzrlib.tests.test_selftest.TestTestResult"
791
"._time_hello_world_encoding")
793
787
def _time_hello_world_encoding(self):
794
788
"""Profile two sleep calls
796
790
This is used to exercise the test framework.
798
self.time(unicode, 'hello', errors='replace')
799
self.time(unicode, 'world', errors='replace')
792
self.time(text_type, 'hello', errors='replace')
793
self.time(text_type, 'world', errors='replace')
801
795
def test_lsprofiling(self):
802
796
"""Verbose test result prints lsprof statistics from test cases."""
803
self.requireFeature(test_lsprof.LSProfFeature)
797
self.requireFeature(features.lsprof_feature)
804
798
result_stream = StringIO()
805
result = bzrlib.tests.VerboseTestResult(
806
unittest._WritelnDecorator(result_stream),
799
result = breezy.tests.VerboseTestResult(
1643
1670
class Test(tests.TestCase):
1645
1672
def setUp(self):
1646
tests.TestCase.setUp(self)
1673
super(Test, self).setUp()
1647
1674
self.orig = self.overrideAttr(obj, 'test_attr', new='modified')
1649
1676
def test_value(self):
1650
1677
self.assertEqual('original', self.orig)
1651
1678
self.assertEqual('modified', obj.test_attr)
1653
test = Test('test_value')
1654
test.run(unittest.TestResult())
1680
self._run_successful_test(Test('test_value'))
1655
1681
self.assertEqual('original', obj.test_attr)
1683
def test_overrideAttr_with_no_existing_value_and_value(self):
1684
# Do not define the test_attribute
1685
obj = self # Make 'obj' visible to the embedded test
1686
class Test(tests.TestCase):
1689
tests.TestCase.setUp(self)
1690
self.orig = self.overrideAttr(obj, 'test_attr', new='modified')
1692
def test_value(self):
1693
self.assertEqual(tests._unitialized_attr, self.orig)
1694
self.assertEqual('modified', obj.test_attr)
1696
self._run_successful_test(Test('test_value'))
1697
self.assertRaises(AttributeError, getattr, obj, 'test_attr')
1699
def test_overrideAttr_with_no_existing_value_and_no_value(self):
1700
# Do not define the test_attribute
1701
obj = self # Make 'obj' visible to the embedded test
1702
class Test(tests.TestCase):
1705
tests.TestCase.setUp(self)
1706
self.orig = self.overrideAttr(obj, 'test_attr')
1708
def test_value(self):
1709
self.assertEqual(tests._unitialized_attr, self.orig)
1710
self.assertRaises(AttributeError, getattr, obj, 'test_attr')
1712
self._run_successful_test(Test('test_value'))
1713
self.assertRaises(AttributeError, getattr, obj, 'test_attr')
1715
def test_recordCalls(self):
1716
from breezy.tests import test_selftest
1717
calls = self.recordCalls(
1718
test_selftest, '_add_numbers')
1719
self.assertEqual(test_selftest._add_numbers(2, 10),
1721
self.assertEqual(calls, [((2, 10), {})])
1724
def _add_numbers(a, b):
1728
class _MissingFeature(features.Feature):
1731
missing_feature = _MissingFeature()
1734
def _get_test(name):
1735
"""Get an instance of a specific example test.
1737
We protect this in a function so that they don't auto-run in the test
1741
class ExampleTests(tests.TestCase):
1743
def test_fail(self):
1744
mutter('this was a failing test')
1745
self.fail('this test will fail')
1747
def test_error(self):
1748
mutter('this test errored')
1749
raise RuntimeError('gotcha')
1751
def test_missing_feature(self):
1752
mutter('missing the feature')
1753
self.requireFeature(missing_feature)
1755
def test_skip(self):
1756
mutter('this test will be skipped')
1757
raise tests.TestSkipped('reason')
1759
def test_success(self):
1760
mutter('this test succeeds')
1762
def test_xfail(self):
1763
mutter('test with expected failure')
1764
self.knownFailure('this_fails')
1766
def test_unexpected_success(self):
1767
mutter('test with unexpected success')
1768
self.expectFailure('should_fail', lambda: None)
1770
return ExampleTests(name)
1773
def _get_skip_reasons(result):
1774
# GZ 2017-06-06: Newer testtools doesn't have this, uses detail instead
1775
return result.skip_reasons
1778
class TestTestCaseLogDetails(tests.TestCase):
1780
def _run_test(self, test_name):
1781
test = _get_test(test_name)
1782
result = testtools.TestResult()
1786
def test_fail_has_log(self):
1787
result = self._run_test('test_fail')
1788
self.assertEqual(1, len(result.failures))
1789
result_content = result.failures[0][1]
1790
self.assertContainsRe(result_content,
1791
'(?m)^(?:Text attachment: )?log(?:$|: )')
1792
self.assertContainsRe(result_content, 'this was a failing test')
1794
def test_error_has_log(self):
1795
result = self._run_test('test_error')
1796
self.assertEqual(1, len(result.errors))
1797
result_content = result.errors[0][1]
1798
self.assertContainsRe(result_content,
1799
'(?m)^(?:Text attachment: )?log(?:$|: )')
1800
self.assertContainsRe(result_content, 'this test errored')
1802
def test_skip_has_no_log(self):
1803
result = self._run_test('test_skip')
1804
reasons = _get_skip_reasons(result)
1805
self.assertEqual({'reason'}, set(reasons))
1806
skips = reasons['reason']
1807
self.assertEqual(1, len(skips))
1809
self.assertFalse('log' in test.getDetails())
1811
def test_missing_feature_has_no_log(self):
1812
# testtools doesn't know about addNotSupported, so it just gets
1813
# considered as a skip
1814
result = self._run_test('test_missing_feature')
1815
reasons = _get_skip_reasons(result)
1816
self.assertEqual({str(missing_feature)}, set(reasons))
1817
skips = reasons[str(missing_feature)]
1818
self.assertEqual(1, len(skips))
1820
self.assertFalse('log' in test.getDetails())
1822
def test_xfail_has_no_log(self):
1823
result = self._run_test('test_xfail')
1824
self.assertEqual(1, len(result.expectedFailures))
1825
result_content = result.expectedFailures[0][1]
1826
self.assertNotContainsRe(result_content,
1827
'(?m)^(?:Text attachment: )?log(?:$|: )')
1828
self.assertNotContainsRe(result_content, 'test with expected failure')
1830
def test_unexpected_success_has_log(self):
1831
result = self._run_test('test_unexpected_success')
1832
self.assertEqual(1, len(result.unexpectedSuccesses))
1833
# Inconsistency, unexpectedSuccesses is a list of tests,
1834
# expectedFailures is a list of reasons?
1835
test = result.unexpectedSuccesses[0]
1836
details = test.getDetails()
1837
self.assertTrue('log' in details)
1840
class TestTestCloning(tests.TestCase):
1841
"""Tests that test cloning of TestCases (as used by multiply_tests)."""
1843
def test_cloned_testcase_does_not_share_details(self):
1844
"""A TestCase cloned with clone_test does not share mutable attributes
1845
such as details or cleanups.
1847
class Test(tests.TestCase):
1849
self.addDetail('foo', Content('text/plain', lambda: 'foo'))
1850
orig_test = Test('test_foo')
1851
cloned_test = tests.clone_test(orig_test, orig_test.id() + '(cloned)')
1852
orig_test.run(unittest.TestResult())
1853
self.assertEqual('foo', orig_test.getDetails()['foo'].iter_bytes())
1854
self.assertEqual(None, cloned_test.getDetails().get('foo'))
1856
def test_double_apply_scenario_preserves_first_scenario(self):
1857
"""Applying two levels of scenarios to a test preserves the attributes
1858
added by both scenarios.
1860
class Test(tests.TestCase):
1863
test = Test('test_foo')
1864
scenarios_x = [('x=1', {'x': 1}), ('x=2', {'x': 2})]
1865
scenarios_y = [('y=1', {'y': 1}), ('y=2', {'y': 2})]
1866
suite = tests.multiply_tests(test, scenarios_x, unittest.TestSuite())
1867
suite = tests.multiply_tests(suite, scenarios_y, unittest.TestSuite())
1868
all_tests = list(tests.iter_suite_tests(suite))
1869
self.assertLength(4, all_tests)
1870
all_xys = sorted((t.x, t.y) for t in all_tests)
1871
self.assertEqual([(1, 1), (1, 2), (2, 1), (2, 2)], all_xys)
1658
1874
# NB: Don't delete this; it's not actually from 0.11!
1659
1875
@deprecated_function(deprecated_in((0, 11, 0)))
1971
2185
load_list='missing file name', list_only=True)
2188
class TestSubunitLogDetails(tests.TestCase, SelfTestHelper):
2190
_test_needs_features = [features.subunit]
2192
def run_subunit_stream(self, test_name):
2193
from subunit import ProtocolTestCase
2195
return TestUtil.TestSuite([_get_test(test_name)])
2196
stream = self.run_selftest(
2197
runner_class=tests.SubUnitBzrRunnerv1,
2198
test_suite_factory=factory)
2199
test = ProtocolTestCase(stream)
2200
result = testtools.TestResult()
2202
content = stream.getvalue()
2203
return content, result
2205
def test_fail_has_log(self):
2206
content, result = self.run_subunit_stream('test_fail')
2207
self.assertEqual(1, len(result.failures))
2208
self.assertContainsRe(content, '(?m)^log$')
2209
self.assertContainsRe(content, 'this test will fail')
2211
def test_error_has_log(self):
2212
content, result = self.run_subunit_stream('test_error')
2213
self.assertContainsRe(content, '(?m)^log$')
2214
self.assertContainsRe(content, 'this test errored')
2216
def test_skip_has_no_log(self):
2217
content, result = self.run_subunit_stream('test_skip')
2218
self.assertNotContainsRe(content, '(?m)^log$')
2219
self.assertNotContainsRe(content, 'this test will be skipped')
2220
reasons = _get_skip_reasons(result)
2221
self.assertEqual({'reason'}, set(reasons))
2222
skips = reasons['reason']
2223
self.assertEqual(1, len(skips))
2225
# RemotedTestCase doesn't preserve the "details"
2226
## self.assertFalse('log' in test.getDetails())
2228
def test_missing_feature_has_no_log(self):
2229
content, result = self.run_subunit_stream('test_missing_feature')
2230
self.assertNotContainsRe(content, '(?m)^log$')
2231
self.assertNotContainsRe(content, 'missing the feature')
2232
reasons = _get_skip_reasons(result)
2233
self.assertEqual({'_MissingFeature\n'}, set(reasons))
2234
skips = reasons['_MissingFeature\n']
2235
self.assertEqual(1, len(skips))
2237
# RemotedTestCase doesn't preserve the "details"
2238
## self.assertFalse('log' in test.getDetails())
2240
def test_xfail_has_no_log(self):
2241
content, result = self.run_subunit_stream('test_xfail')
2242
self.assertNotContainsRe(content, '(?m)^log$')
2243
self.assertNotContainsRe(content, 'test with expected failure')
2244
self.assertEqual(1, len(result.expectedFailures))
2245
result_content = result.expectedFailures[0][1]
2246
self.assertNotContainsRe(result_content,
2247
'(?m)^(?:Text attachment: )?log(?:$|: )')
2248
self.assertNotContainsRe(result_content, 'test with expected failure')
2250
def test_unexpected_success_has_log(self):
2251
content, result = self.run_subunit_stream('test_unexpected_success')
2252
self.assertContainsRe(content, '(?m)^log$')
2253
self.assertContainsRe(content, 'test with unexpected success')
2254
# GZ 2011-05-18: Old versions of subunit treat unexpected success as a
2255
# success, if a min version check is added remove this
2256
from subunit import TestProtocolClient as _Client
2257
if _Client.addUnexpectedSuccess.__func__ is _Client.addSuccess.__func__:
2258
self.expectFailure('subunit treats "unexpectedSuccess"'
2259
' as a plain success',
2260
self.assertEqual, 1, len(result.unexpectedSuccesses))
2261
self.assertEqual(1, len(result.unexpectedSuccesses))
2262
test = result.unexpectedSuccesses[0]
2263
# RemotedTestCase doesn't preserve the "details"
2264
## self.assertTrue('log' in test.getDetails())
2266
def test_success_has_no_log(self):
2267
content, result = self.run_subunit_stream('test_success')
2268
self.assertEqual(1, result.testsRun)
2269
self.assertNotContainsRe(content, '(?m)^log$')
2270
self.assertNotContainsRe(content, 'this test succeeds')
1974
2273
class TestRunBzr(tests.TestCase):
2264
2563
class TestStartBzrSubProcess(tests.TestCase):
2564
"""Stub test start_bzr_subprocess."""
2266
def check_popen_state(self):
2267
"""Replace to make assertions when popen is called."""
2566
def _subprocess_log_cleanup(self):
2567
"""Inhibits the base version as we don't produce a log file."""
2269
2569
def _popen(self, *args, **kwargs):
2270
"""Record the command that is run, so that we can ensure it is correct"""
2570
"""Override the base version to record the command that is run.
2572
From there we can ensure it is correct without spawning a real process.
2271
2574
self.check_popen_state()
2272
2575
self._popen_args = args
2273
2576
self._popen_kwargs = kwargs
2274
2577
raise _DontSpawnProcess()
2579
def check_popen_state(self):
2580
"""Replace to make assertions when popen is called."""
2276
2582
def test_run_bzr_subprocess_no_plugins(self):
2277
2583
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [])
2278
2584
command = self._popen_args[0]
2279
2585
self.assertEqual(sys.executable, command[0])
2280
self.assertEqual(self.get_bzr_path(), command[1])
2586
self.assertEqual(self.get_brz_path(), command[1])
2281
2587
self.assertEqual(['--no-plugins'], command[2:])
2283
2589
def test_allow_plugins(self):
2284
2590
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2286
2592
command = self._popen_args[0]
2287
2593
self.assertEqual([], command[2:])
2289
2595
def test_set_env(self):
2290
self.failIf('EXISTANT_ENV_VAR' in os.environ)
2596
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2291
2597
# set in the child
2292
2598
def check_environment():
2293
2599
self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR'])
2294
2600
self.check_popen_state = check_environment
2295
2601
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2296
env_changes={'EXISTANT_ENV_VAR':'set variable'})
2602
env_changes={'EXISTANT_ENV_VAR':'set variable'})
2297
2603
# not set in theparent
2298
2604
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2300
2606
def test_run_bzr_subprocess_env_del(self):
2301
2607
"""run_bzr_subprocess can remove environment variables too."""
2302
self.failIf('EXISTANT_ENV_VAR' in os.environ)
2608
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2303
2609
def check_environment():
2304
2610
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2305
2611
os.environ['EXISTANT_ENV_VAR'] = 'set variable'
2306
2612
self.check_popen_state = check_environment
2307
2613
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2308
env_changes={'EXISTANT_ENV_VAR':None})
2614
env_changes={'EXISTANT_ENV_VAR':None})
2309
2615
# Still set in parent
2310
2616
self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR'])
2311
2617
del os.environ['EXISTANT_ENV_VAR']
2313
2619
def test_env_del_missing(self):
2314
self.failIf('NON_EXISTANT_ENV_VAR' in os.environ)
2620
self.assertFalse('NON_EXISTANT_ENV_VAR' in os.environ)
2315
2621
def check_environment():
2316
2622
self.assertFalse('NON_EXISTANT_ENV_VAR' in os.environ)
2317
2623
self.check_popen_state = check_environment
2318
2624
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2319
env_changes={'NON_EXISTANT_ENV_VAR':None})
2625
env_changes={'NON_EXISTANT_ENV_VAR':None})
2321
2627
def test_working_dir(self):
2322
2628
"""Test that we can specify the working dir for the child"""
2354
2659
result = self.finish_bzr_subprocess(process, send_signal=signal.SIGINT,
2356
2661
self.assertEqual('', result[0])
2357
self.assertEqual('bzr: interrupted\n', result[1])
2360
class TestFeature(tests.TestCase):
2362
def test_caching(self):
2363
"""Feature._probe is called by the feature at most once."""
2364
class InstrumentedFeature(tests.Feature):
2366
super(InstrumentedFeature, self).__init__()
2369
self.calls.append('_probe')
2371
feature = InstrumentedFeature()
2373
self.assertEqual(['_probe'], feature.calls)
2375
self.assertEqual(['_probe'], feature.calls)
2377
def test_named_str(self):
2378
"""Feature.__str__ should thunk to feature_name()."""
2379
class NamedFeature(tests.Feature):
2380
def feature_name(self):
2382
feature = NamedFeature()
2383
self.assertEqual('symlinks', str(feature))
2385
def test_default_str(self):
2386
"""Feature.__str__ should default to __class__.__name__."""
2387
class NamedFeature(tests.Feature):
2389
feature = NamedFeature()
2390
self.assertEqual('NamedFeature', str(feature))
2393
class TestUnavailableFeature(tests.TestCase):
2395
def test_access_feature(self):
2396
feature = tests.Feature()
2397
exception = tests.UnavailableFeature(feature)
2398
self.assertIs(feature, exception.args[0])
2401
simple_thunk_feature = tests._CompatabilityThunkFeature(
2402
deprecated_in((2, 1, 0)),
2403
'bzrlib.tests.test_selftest',
2404
'simple_thunk_feature','UnicodeFilename',
2405
replacement_module='bzrlib.tests'
2408
class Test_CompatibilityFeature(tests.TestCase):
2410
def test_does_thunk(self):
2411
res = self.callDeprecated(
2412
['bzrlib.tests.test_selftest.simple_thunk_feature was deprecated'
2413
' in version 2.1.0. Use bzrlib.tests.UnicodeFilename instead.'],
2414
simple_thunk_feature.available)
2415
self.assertEqual(tests.UnicodeFilename.available(), res)
2418
class TestModuleAvailableFeature(tests.TestCase):
2420
def test_available_module(self):
2421
feature = tests.ModuleAvailableFeature('bzrlib.tests')
2422
self.assertEqual('bzrlib.tests', feature.module_name)
2423
self.assertEqual('bzrlib.tests', str(feature))
2424
self.assertTrue(feature.available())
2425
self.assertIs(tests, feature.module)
2427
def test_unavailable_module(self):
2428
feature = tests.ModuleAvailableFeature('bzrlib.no_such_module_exists')
2429
self.assertEqual('bzrlib.no_such_module_exists', str(feature))
2430
self.assertFalse(feature.available())
2431
self.assertIs(None, feature.module)
2662
self.assertEqual('brz: interrupted\n', result[1])
2434
2665
class TestSelftestFiltering(tests.TestCase):
2436
2667
def setUp(self):
2437
tests.TestCase.setUp(self)
2668
super(TestSelftestFiltering, self).setUp()
2438
2669
self.suite = TestUtil.TestSuite()
2439
2670
self.loader = TestUtil.TestLoader()
2440
2671
self.suite.addTest(self.loader.loadTestsFromModule(
2441
sys.modules['bzrlib.tests.test_selftest']))
2672
sys.modules['breezy.tests.test_selftest']))
2442
2673
self.all_names = _test_ids(self.suite)
2444
2675
def test_condition_id_re(self):
2445
test_name = ('bzrlib.tests.test_selftest.TestSelftestFiltering.'
2676
test_name = ('breezy.tests.test_selftest.TestSelftestFiltering.'
2446
2677
'test_condition_id_re')
2447
2678
filtered_suite = tests.filter_suite_by_condition(
2448
2679
self.suite, tests.condition_id_re('test_condition_id_re'))
2449
2680
self.assertEqual([test_name], _test_ids(filtered_suite))
2451
2682
def test_condition_id_in_list(self):
2452
test_names = ['bzrlib.tests.test_selftest.TestSelftestFiltering.'
2683
test_names = ['breezy.tests.test_selftest.TestSelftestFiltering.'
2453
2684
'test_condition_id_in_list']
2454
2685
id_list = tests.TestIdList(test_names)
2455
2686
filtered_suite = tests.filter_suite_by_condition(
2953
3186
def test_predefined_prefixes(self):
2954
3187
tpr = tests.test_prefix_alias_registry
2955
self.assertEquals('bzrlib', tpr.resolve_alias('bzrlib'))
2956
self.assertEquals('bzrlib.doc', tpr.resolve_alias('bd'))
2957
self.assertEquals('bzrlib.utils', tpr.resolve_alias('bu'))
2958
self.assertEquals('bzrlib.tests', tpr.resolve_alias('bt'))
2959
self.assertEquals('bzrlib.tests.blackbox', tpr.resolve_alias('bb'))
2960
self.assertEquals('bzrlib.plugins', tpr.resolve_alias('bp'))
3188
self.assertEqual('breezy', tpr.resolve_alias('breezy'))
3189
self.assertEqual('breezy.doc', tpr.resolve_alias('bd'))
3190
self.assertEqual('breezy.utils', tpr.resolve_alias('bu'))
3191
self.assertEqual('breezy.tests', tpr.resolve_alias('bt'))
3192
self.assertEqual('breezy.tests.blackbox', tpr.resolve_alias('bb'))
3193
self.assertEqual('breezy.plugins', tpr.resolve_alias('bp'))
3196
class TestThreadLeakDetection(tests.TestCase):
3197
"""Ensure when tests leak threads we detect and report it"""
3199
class LeakRecordingResult(tests.ExtendedTestResult):
3201
tests.ExtendedTestResult.__init__(self, StringIO(), 0, 1)
3203
def _report_thread_leak(self, test, leaks, alive):
3204
self.leaks.append((test, leaks))
3206
def test_testcase_without_addCleanups(self):
3207
"""Check old TestCase instances don't break with leak detection"""
3208
class Test(unittest.TestCase):
3211
result = self.LeakRecordingResult()
3213
result.startTestRun()
3215
result.stopTestRun()
3216
self.assertEqual(result._tests_leaking_threads_count, 0)
3217
self.assertEqual(result.leaks, [])
3219
def test_thread_leak(self):
3220
"""Ensure a thread that outlives the running of a test is reported
3222
Uses a thread that blocks on an event, and is started by the inner
3223
test case. As the thread outlives the inner case's run, it should be
3224
detected as a leak, but the event is then set so that the thread can
3225
be safely joined in cleanup so it's not leaked for real.
3227
event = threading.Event()
3228
thread = threading.Thread(name="Leaker", target=event.wait)
3229
class Test(tests.TestCase):
3230
def test_leak(self):
3232
result = self.LeakRecordingResult()
3233
test = Test("test_leak")
3234
self.addCleanup(thread.join)
3235
self.addCleanup(event.set)
3236
result.startTestRun()
3238
result.stopTestRun()
3239
self.assertEqual(result._tests_leaking_threads_count, 1)
3240
self.assertEqual(result._first_thread_leaker_id, test.id())
3241
self.assertEqual(result.leaks, [(test, {thread})])
3242
self.assertContainsString(result.stream.getvalue(), "leaking threads")
3244
def test_multiple_leaks(self):
3245
"""Check multiple leaks are blamed on the test cases at fault
3247
Same concept as the previous test, but has one inner test method that
3248
leaks two threads, and one that doesn't leak at all.
3250
event = threading.Event()
3251
thread_a = threading.Thread(name="LeakerA", target=event.wait)
3252
thread_b = threading.Thread(name="LeakerB", target=event.wait)
3253
thread_c = threading.Thread(name="LeakerC", target=event.wait)
3254
class Test(tests.TestCase):
3255
def test_first_leak(self):
3257
def test_second_no_leak(self):
3259
def test_third_leak(self):
3262
result = self.LeakRecordingResult()
3263
first_test = Test("test_first_leak")
3264
third_test = Test("test_third_leak")
3265
self.addCleanup(thread_a.join)
3266
self.addCleanup(thread_b.join)
3267
self.addCleanup(thread_c.join)
3268
self.addCleanup(event.set)
3269
result.startTestRun()
3271
[first_test, Test("test_second_no_leak"), third_test]
3273
result.stopTestRun()
3274
self.assertEqual(result._tests_leaking_threads_count, 2)
3275
self.assertEqual(result._first_thread_leaker_id, first_test.id())
3276
self.assertEqual(result.leaks, [
3277
(first_test, {thread_b}),
3278
(third_test, {thread_a, thread_c})])
3279
self.assertContainsString(result.stream.getvalue(), "leaking threads")
3282
class TestPostMortemDebugging(tests.TestCase):
3283
"""Check post mortem debugging works when tests fail or error"""
3285
class TracebackRecordingResult(tests.ExtendedTestResult):
3287
tests.ExtendedTestResult.__init__(self, StringIO(), 0, 1)
3288
self.postcode = None
3289
def _post_mortem(self, tb=None):
3290
"""Record the code object at the end of the current traceback"""
3291
tb = tb or sys.exc_info()[2]
3294
while next is not None:
3297
self.postcode = tb.tb_frame.f_code
3298
def report_error(self, test, err):
3300
def report_failure(self, test, err):
3303
def test_location_unittest_error(self):
3304
"""Needs right post mortem traceback with erroring unittest case"""
3305
class Test(unittest.TestCase):
3308
result = self.TracebackRecordingResult()
3310
self.assertEqual(result.postcode, Test.runTest.__code__)
3312
def test_location_unittest_failure(self):
3313
"""Needs right post mortem traceback with failing unittest case"""
3314
class Test(unittest.TestCase):
3316
raise self.failureException
3317
result = self.TracebackRecordingResult()
3319
self.assertEqual(result.postcode, Test.runTest.__code__)
3321
def test_location_bt_error(self):
3322
"""Needs right post mortem traceback with erroring breezy.tests case"""
3323
class Test(tests.TestCase):
3324
def test_error(self):
3326
result = self.TracebackRecordingResult()
3327
Test("test_error").run(result)
3328
self.assertEqual(result.postcode, Test.test_error.__code__)
3330
def test_location_bt_failure(self):
3331
"""Needs right post mortem traceback with failing breezy.tests case"""
3332
class Test(tests.TestCase):
3333
def test_failure(self):
3334
raise self.failureException
3335
result = self.TracebackRecordingResult()
3336
Test("test_failure").run(result)
3337
self.assertEqual(result.postcode, Test.test_failure.__code__)
3339
def test_env_var_triggers_post_mortem(self):
3340
"""Check pdb.post_mortem is called iff BRZ_TEST_PDB is set"""
3342
result = tests.ExtendedTestResult(StringIO(), 0, 1)
3343
post_mortem_calls = []
3344
self.overrideAttr(pdb, "post_mortem", post_mortem_calls.append)
3345
self.overrideEnv('BRZ_TEST_PDB', None)
3346
result._post_mortem(1)
3347
self.overrideEnv('BRZ_TEST_PDB', 'on')
3348
result._post_mortem(2)
3349
self.assertEqual([2], post_mortem_calls)
2963
3352
class TestRunSuite(tests.TestCase):
2976
3365
self.verbosity)
2977
3366
tests.run_suite(suite, runner_class=MyRunner, stream=StringIO())
2978
3367
self.assertLength(1, calls)
3370
class _Selftest(object):
3371
"""Mixin for tests needing full selftest output"""
3373
def _inject_stream_into_subunit(self, stream):
3374
"""To be overridden by subclasses that run tests out of process"""
3376
def _run_selftest(self, **kwargs):
3378
self._inject_stream_into_subunit(sio)
3379
tests.selftest(stream=sio, stop_on_failure=False, **kwargs)
3380
return sio.getvalue()
3383
class _ForkedSelftest(_Selftest):
3384
"""Mixin for tests needing full selftest output with forked children"""
3386
_test_needs_features = [features.subunit]
3388
def _inject_stream_into_subunit(self, stream):
3389
"""Monkey-patch subunit so the extra output goes to stream not stdout
3391
Some APIs need rewriting so this kind of bogus hackery can be replaced
3392
by passing the stream param from run_tests down into ProtocolTestCase.
3394
from subunit import ProtocolTestCase
3395
_original_init = ProtocolTestCase.__init__
3396
def _init_with_passthrough(self, *args, **kwargs):
3397
_original_init(self, *args, **kwargs)
3398
self._passthrough = stream
3399
self.overrideAttr(ProtocolTestCase, "__init__", _init_with_passthrough)
3401
def _run_selftest(self, **kwargs):
3402
# GZ 2011-05-26: Add a PosixSystem feature so this check can go away
3403
if getattr(os, "fork", None) is None:
3404
raise tests.TestNotApplicable("Platform doesn't support forking")
3405
# Make sure the fork code is actually invoked by claiming two cores
3406
self.overrideAttr(osutils, "local_concurrency", lambda: 2)
3407
kwargs.setdefault("suite_decorators", []).append(tests.fork_decorator)
3408
return super(_ForkedSelftest, self)._run_selftest(**kwargs)
3411
class TestParallelFork(_ForkedSelftest, tests.TestCase):
3412
"""Check operation of --parallel=fork selftest option"""
3414
def test_error_in_child_during_fork(self):
3415
"""Error in a forked child during test setup should get reported"""
3416
class Test(tests.TestCase):
3417
def testMethod(self):
3419
# We don't care what, just break something that a child will run
3420
self.overrideAttr(tests, "workaround_zealous_crypto_random", None)
3421
out = self._run_selftest(test_suite_factory=Test)
3422
# Lines from the tracebacks of the two child processes may be mixed
3423
# together due to the way subunit parses and forwards the streams,
3424
# so permit extra lines between each part of the error output.
3425
self.assertContainsRe(out,
3428
".+ in fork_for_tests\n"
3430
"\\s*workaround_zealous_crypto_random\\(\\)\n"
3435
class TestUncollectedWarnings(_Selftest, tests.TestCase):
3436
"""Check a test case still alive after being run emits a warning"""
3438
class Test(tests.TestCase):
3439
def test_pass(self):
3441
def test_self_ref(self):
3442
self.also_self = self.test_self_ref
3443
def test_skip(self):
3444
self.skipTest("Don't need")
3446
def _get_suite(self):
3447
return TestUtil.TestSuite([
3448
self.Test("test_pass"),
3449
self.Test("test_self_ref"),
3450
self.Test("test_skip"),
3453
def _run_selftest_with_suite(self, **kwargs):
3454
old_flags = tests.selftest_debug_flags
3455
tests.selftest_debug_flags = old_flags.union(["uncollected_cases"])
3456
gc_on = gc.isenabled()
3460
output = self._run_selftest(test_suite_factory=self._get_suite,
3465
tests.selftest_debug_flags = old_flags
3466
self.assertNotContainsRe(output, "Uncollected test case.*test_pass")
3467
self.assertContainsRe(output, "Uncollected test case.*test_self_ref")
3470
def test_testsuite(self):
3471
self._run_selftest_with_suite()
3473
def test_pattern(self):
3474
out = self._run_selftest_with_suite(pattern="test_(?:pass|self_ref)$")
3475
self.assertNotContainsRe(out, "test_skip")
3477
def test_exclude_pattern(self):
3478
out = self._run_selftest_with_suite(exclude_pattern="test_skip$")
3479
self.assertNotContainsRe(out, "test_skip")
3481
def test_random_seed(self):
3482
self._run_selftest_with_suite(random_seed="now")
3484
def test_matching_tests_first(self):
3485
self._run_selftest_with_suite(matching_tests_first=True,
3486
pattern="test_self_ref$")
3488
def test_starting_with_and_exclude(self):
3489
out = self._run_selftest_with_suite(starting_with=["bt."],
3490
exclude_pattern="test_skip$")
3491
self.assertNotContainsRe(out, "test_skip")
3493
def test_additonal_decorator(self):
3494
out = self._run_selftest_with_suite(
3495
suite_decorators=[tests.TestDecorator])
3498
class TestUncollectedWarningsSubunit(TestUncollectedWarnings):
3499
"""Check warnings from tests staying alive are emitted with subunit"""
3501
_test_needs_features = [features.subunit]
3503
def _run_selftest_with_suite(self, **kwargs):
3504
return TestUncollectedWarnings._run_selftest_with_suite(
3505
self, runner_class=tests.SubUnitBzrRunnerv1, **kwargs)
3508
class TestUncollectedWarningsForked(_ForkedSelftest, TestUncollectedWarnings):
3509
"""Check warnings from tests staying alive are emitted when forking"""
3512
class TestEnvironHandling(tests.TestCase):
3514
def test_overrideEnv_None_called_twice_doesnt_leak(self):
3515
self.assertFalse('MYVAR' in os.environ)
3516
self.overrideEnv('MYVAR', '42')
3517
# We use an embedded test to make sure we fix the _captureVar bug
3518
class Test(tests.TestCase):
3520
# The first call save the 42 value
3521
self.overrideEnv('MYVAR', None)
3522
self.assertEqual(None, os.environ.get('MYVAR'))
3523
# Make sure we can call it twice
3524
self.overrideEnv('MYVAR', None)
3525
self.assertEqual(None, os.environ.get('MYVAR'))
3527
result = tests.TextTestResult(output, 0, 1)
3528
Test('test_me').run(result)
3529
if not result.wasStrictlySuccessful():
3530
self.fail(output.getvalue())
3531
# We get our value back
3532
self.assertEqual('42', os.environ.get('MYVAR'))
3535
class TestIsolatedEnv(tests.TestCase):
3536
"""Test isolating tests from os.environ.
3538
Since we use tests that are already isolated from os.environ a bit of care
3539
should be taken when designing the tests to avoid bootstrap side-effects.
3540
The tests start an already clean os.environ which allow doing valid
3541
assertions about which variables are present or not and design tests around
3545
class ScratchMonkey(tests.TestCase):
3550
def test_basics(self):
3551
# Make sure we know the definition of BRZ_HOME: not part of os.environ
3552
# for tests.TestCase.
3553
self.assertTrue('BRZ_HOME' in tests.isolated_environ)
3554
self.assertEqual(None, tests.isolated_environ['BRZ_HOME'])
3555
# Being part of isolated_environ, BRZ_HOME should not appear here
3556
self.assertFalse('BRZ_HOME' in os.environ)
3557
# Make sure we know the definition of LINES: part of os.environ for
3559
self.assertTrue('LINES' in tests.isolated_environ)
3560
self.assertEqual('25', tests.isolated_environ['LINES'])
3561
self.assertEqual('25', os.environ['LINES'])
3563
def test_injecting_unknown_variable(self):
3564
# BRZ_HOME is known to be absent from os.environ
3565
test = self.ScratchMonkey('test_me')
3566
tests.override_os_environ(test, {'BRZ_HOME': 'foo'})
3567
self.assertEqual('foo', os.environ['BRZ_HOME'])
3568
tests.restore_os_environ(test)
3569
self.assertFalse('BRZ_HOME' in os.environ)
3571
def test_injecting_known_variable(self):
3572
test = self.ScratchMonkey('test_me')
3573
# LINES is known to be present in os.environ
3574
tests.override_os_environ(test, {'LINES': '42'})
3575
self.assertEqual('42', os.environ['LINES'])
3576
tests.restore_os_environ(test)
3577
self.assertEqual('25', os.environ['LINES'])
3579
def test_deleting_variable(self):
3580
test = self.ScratchMonkey('test_me')
3581
# LINES is known to be present in os.environ
3582
tests.override_os_environ(test, {'LINES': None})
3583
self.assertTrue('LINES' not in os.environ)
3584
tests.restore_os_environ(test)
3585
self.assertEqual('25', os.environ['LINES'])
3588
class TestDocTestSuiteIsolation(tests.TestCase):
3589
"""Test that `tests.DocTestSuite` isolates doc tests from os.environ.
3591
Since tests.TestCase alreay provides an isolation from os.environ, we use
3592
the clean environment as a base for testing. To precisely capture the
3593
isolation provided by tests.DocTestSuite, we use doctest.DocTestSuite to
3596
We want to make sure `tests.DocTestSuite` respect `tests.isolated_environ`,
3597
not `os.environ` so each test overrides it to suit its needs.
3601
def get_doctest_suite_for_string(self, klass, string):
3602
class Finder(doctest.DocTestFinder):
3604
def find(*args, **kwargs):
3605
test = doctest.DocTestParser().get_doctest(
3606
string, {}, 'foo', 'foo.py', 0)
3609
suite = klass(test_finder=Finder())
3612
def run_doctest_suite_for_string(self, klass, string):
3613
suite = self.get_doctest_suite_for_string(klass, string)
3615
result = tests.TextTestResult(output, 0, 1)
3617
return result, output
3619
def assertDocTestStringSucceds(self, klass, string):
3620
result, output = self.run_doctest_suite_for_string(klass, string)
3621
if not result.wasStrictlySuccessful():
3622
self.fail(output.getvalue())
3624
def assertDocTestStringFails(self, klass, string):
3625
result, output = self.run_doctest_suite_for_string(klass, string)
3626
if result.wasStrictlySuccessful():
3627
self.fail(output.getvalue())
3629
def test_injected_variable(self):
3630
self.overrideAttr(tests, 'isolated_environ', {'LINES': '42'})
3633
>>> os.environ['LINES']
3636
# doctest.DocTestSuite fails as it sees '25'
3637
self.assertDocTestStringFails(doctest.DocTestSuite, test)
3638
# tests.DocTestSuite sees '42'
3639
self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
3641
def test_deleted_variable(self):
3642
self.overrideAttr(tests, 'isolated_environ', {'LINES': None})
3645
>>> os.environ.get('LINES')
3647
# doctest.DocTestSuite fails as it sees '25'
3648
self.assertDocTestStringFails(doctest.DocTestSuite, test)
3649
# tests.DocTestSuite sees None
3650
self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
3653
class TestSelftestExcludePatterns(tests.TestCase):
3656
super(TestSelftestExcludePatterns, self).setUp()
3657
self.overrideAttr(tests, 'test_suite', self.suite_factory)
3659
def suite_factory(self, keep_only=None, starting_with=None):
3660
"""A test suite factory with only a few tests."""
3661
class Test(tests.TestCase):
3663
# We don't need the full class path
3664
return self._testMethodName
3671
return TestUtil.TestSuite([Test("a"), Test("b"), Test("c")])
3673
def assertTestList(self, expected, *selftest_args):
3674
# We rely on setUp installing the right test suite factory so we can
3675
# test at the command level without loading the whole test suite
3676
out, err = self.run_bzr(('selftest', '--list') + selftest_args)
3677
actual = out.splitlines()
3678
self.assertEqual(expected, actual)
3680
def test_full_list(self):
3681
self.assertTestList(['a', 'b', 'c'])
3683
def test_single_exclude(self):
3684
self.assertTestList(['b', 'c'], '-x', 'a')
3686
def test_mutiple_excludes(self):
3687
self.assertTestList(['c'], '-x', 'a', '-x', 'b')
3690
class TestCounterHooks(tests.TestCase, SelfTestHelper):
3692
_test_needs_features = [features.subunit]
3695
super(TestCounterHooks, self).setUp()
3696
class Test(tests.TestCase):
3699
super(Test, self).setUp()
3700
self.hooks = hooks.Hooks()
3701
self.hooks.add_hook('myhook', 'Foo bar blah', (2, 4))
3702
self.install_counter_hook(self.hooks, 'myhook')
3707
def run_hook_once(self):
3708
for hook in self.hooks['myhook']:
3711
self.test_class = Test
3713
def assertHookCalls(self, expected_calls, test_name):
3714
test = self.test_class(test_name)
3715
result = unittest.TestResult()
3717
self.assertTrue(hasattr(test, '_counters'))
3718
self.assertTrue('myhook' in test._counters)
3719
self.assertEqual(expected_calls, test._counters['myhook'])
3721
def test_no_hook(self):
3722
self.assertHookCalls(0, 'no_hook')
3724
def test_run_hook_once(self):
3725
tt = features.testtools
3726
if tt.module.__version__ < (0, 9, 8):
3727
raise tests.TestSkipped('testtools-0.9.8 required for addDetail')
3728
self.assertHookCalls(1, 'run_hook_once')