634
610
test = TestDanglingLock('test_function')
635
611
result = test.run()
636
total_failures = result.errors + result.failures
637
612
if self._lock_check_thorough:
638
self.assertEqual(1, len(total_failures))
613
self.assertEqual(1, len(result.errors))
640
615
# When _lock_check_thorough is disabled, then we don't trigger a
642
self.assertEqual(0, len(total_failures))
617
self.assertEqual(0, len(result.errors))
645
620
class TestTestCaseWithTransport(tests.TestCaseWithTransport):
646
621
"""Tests for the convenience functions TestCaseWithTransport introduces."""
648
623
def test_get_readonly_url_none(self):
624
from bzrlib.transport import get_transport
625
from bzrlib.transport.memory import MemoryServer
649
626
from bzrlib.transport.readonly import ReadonlyTransportDecorator
650
self.vfs_transport_factory = memory.MemoryServer
627
self.vfs_transport_factory = MemoryServer
651
628
self.transport_readonly_server = None
652
629
# calling get_readonly_transport() constructs a decorator on the url
654
631
url = self.get_readonly_url()
655
632
url2 = self.get_readonly_url('foo/bar')
656
t = transport.get_transport(url)
657
t2 = transport.get_transport(url2)
658
self.assertIsInstance(t, ReadonlyTransportDecorator)
659
self.assertIsInstance(t2, ReadonlyTransportDecorator)
633
t = get_transport(url)
634
t2 = get_transport(url2)
635
self.failUnless(isinstance(t, ReadonlyTransportDecorator))
636
self.failUnless(isinstance(t2, ReadonlyTransportDecorator))
660
637
self.assertEqual(t2.base[:-1], t.abspath('foo/bar'))
662
639
def test_get_readonly_url_http(self):
663
640
from bzrlib.tests.http_server import HttpServer
641
from bzrlib.transport import get_transport
642
from bzrlib.transport.local import LocalURLServer
664
643
from bzrlib.transport.http import HttpTransportBase
665
self.transport_server = test_server.LocalURLServer
644
self.transport_server = LocalURLServer
666
645
self.transport_readonly_server = HttpServer
667
646
# calling get_readonly_transport() gives us a HTTP server instance.
668
647
url = self.get_readonly_url()
669
648
url2 = self.get_readonly_url('foo/bar')
670
649
# the transport returned may be any HttpTransportBase subclass
671
t = transport.get_transport(url)
672
t2 = transport.get_transport(url2)
673
self.assertIsInstance(t, HttpTransportBase)
674
self.assertIsInstance(t2, HttpTransportBase)
650
t = get_transport(url)
651
t2 = get_transport(url2)
652
self.failUnless(isinstance(t, HttpTransportBase))
653
self.failUnless(isinstance(t2, HttpTransportBase))
675
654
self.assertEqual(t2.base[:-1], t.abspath('foo/bar'))
677
656
def test_is_directory(self):
772
752
self.check_timing(ShortDelayTestCase('test_short_delay'),
755
def _patch_get_bzr_source_tree(self):
756
# Reading from the actual source tree breaks isolation, but we don't
757
# want to assume that thats *all* that would happen.
758
self.overrideAttr(bzrlib.version, '_get_bzr_source_tree', lambda: None)
760
def test_assigned_benchmark_file_stores_date(self):
761
self._patch_get_bzr_source_tree()
763
result = bzrlib.tests.TextTestResult(self._log_file,
768
output_string = output.getvalue()
769
# if you are wondering about the regexp please read the comment in
770
# test_bench_history (bzrlib.tests.test_selftest.TestRunner)
771
# XXX: what comment? -- Andrew Bennetts
772
self.assertContainsRe(output_string, "--date [0-9.]+")
774
def test_benchhistory_records_test_times(self):
775
self._patch_get_bzr_source_tree()
776
result_stream = StringIO()
777
result = bzrlib.tests.TextTestResult(
781
bench_history=result_stream
784
# we want profile a call and check that its test duration is recorded
785
# make a new test instance that when run will generate a benchmark
786
example_test_case = TestTestResult("_time_hello_world_encoding")
787
# execute the test, which should succeed and record times
788
example_test_case.run(result)
789
lines = result_stream.getvalue().splitlines()
790
self.assertEqual(2, len(lines))
791
self.assertContainsRe(lines[1],
792
" *[0-9]+ms bzrlib.tests.test_selftest.TestTestResult"
793
"._time_hello_world_encoding")
775
795
def _time_hello_world_encoding(self):
776
796
"""Profile two sleep calls
817
837
self.assertContainsRe(output,
818
838
r"LSProf output for <type 'unicode'>\(\('world',\), {'errors': 'replace'}\)\n")
820
def test_uses_time_from_testtools(self):
821
"""Test case timings in verbose results should use testtools times"""
823
class TimeAddedVerboseTestResult(tests.VerboseTestResult):
824
def startTest(self, test):
825
self.time(datetime.datetime.utcfromtimestamp(1.145))
826
super(TimeAddedVerboseTestResult, self).startTest(test)
827
def addSuccess(self, test):
828
self.time(datetime.datetime.utcfromtimestamp(51.147))
829
super(TimeAddedVerboseTestResult, self).addSuccess(test)
830
def report_tests_starting(self): pass
832
self.get_passing_test().run(TimeAddedVerboseTestResult(sio, 0, 2))
833
self.assertEndsWith(sio.getvalue(), "OK 50002ms\n")
835
840
def test_known_failure(self):
836
841
"""A KnownFailure being raised should trigger several result actions."""
837
842
class InstrumentedTestResult(tests.ExtendedTestResult):
838
843
def stopTestRun(self): pass
839
def report_tests_starting(self): pass
844
def startTests(self): pass
845
def report_test_start(self, test): pass
840
846
def report_known_failure(self, test, err=None, details=None):
841
847
self._call = test, 'known failure'
842
848
result = InstrumentedTestResult(None, None, None, None)
1217
def test_verbose_test_count(self):
1218
"""A verbose test run reports the right test count at the start"""
1219
suite = TestUtil.TestSuite([
1220
unittest.FunctionTestCase(lambda:None),
1221
unittest.FunctionTestCase(lambda:None)])
1222
self.assertEqual(suite.countTestCases(), 2)
1224
runner = tests.TextTestRunner(stream=stream, verbosity=2)
1225
# Need to use the CountingDecorator as that's what sets num_tests
1226
result = self.run_test_runner(runner, tests.CountingDecorator(suite))
1227
self.assertStartsWith(stream.getvalue(), "running 2 tests")
1195
def _patch_get_bzr_source_tree(self):
1196
# Reading from the actual source tree breaks isolation, but we don't
1197
# want to assume that thats *all* that would happen.
1198
self._get_source_tree_calls = []
1200
self._get_source_tree_calls.append("called")
1202
self.overrideAttr(bzrlib.version, '_get_bzr_source_tree', new_get)
1204
def test_bench_history(self):
1205
# tests that the running the benchmark passes bench_history into
1206
# the test result object. We can tell that happens if
1207
# _get_bzr_source_tree is called.
1208
self._patch_get_bzr_source_tree()
1209
test = TestRunner('dummy_test')
1211
runner = tests.TextTestRunner(stream=self._log_file,
1212
bench_history=output)
1213
result = self.run_test_runner(runner, test)
1214
output_string = output.getvalue()
1215
self.assertContainsRe(output_string, "--date [0-9.]+")
1216
self.assertLength(1, self._get_source_tree_calls)
1229
1218
def test_startTestRun(self):
1230
1219
"""run should call result.startTestRun()"""
1232
class LoggingDecorator(ExtendedToOriginalDecorator):
1221
class LoggingDecorator(tests.ForwardingResult):
1233
1222
def startTestRun(self):
1234
ExtendedToOriginalDecorator.startTestRun(self)
1223
tests.ForwardingResult.startTestRun(self)
1235
1224
calls.append('startTestRun')
1236
1225
test = unittest.FunctionTestCase(lambda:None)
1237
1226
stream = StringIO()
1685
1657
self.assertEqual('original', obj.test_attr)
1688
class _MissingFeature(tests.Feature):
1691
missing_feature = _MissingFeature()
1694
def _get_test(name):
1695
"""Get an instance of a specific example test.
1697
We protect this in a function so that they don't auto-run in the test
1701
class ExampleTests(tests.TestCase):
1703
def test_fail(self):
1704
mutter('this was a failing test')
1705
self.fail('this test will fail')
1707
def test_error(self):
1708
mutter('this test errored')
1709
raise RuntimeError('gotcha')
1711
def test_missing_feature(self):
1712
mutter('missing the feature')
1713
self.requireFeature(missing_feature)
1715
def test_skip(self):
1716
mutter('this test will be skipped')
1717
raise tests.TestSkipped('reason')
1719
def test_success(self):
1720
mutter('this test succeeds')
1722
def test_xfail(self):
1723
mutter('test with expected failure')
1724
self.knownFailure('this_fails')
1726
def test_unexpected_success(self):
1727
mutter('test with unexpected success')
1728
self.expectFailure('should_fail', lambda: None)
1730
return ExampleTests(name)
1733
class TestTestCaseLogDetails(tests.TestCase):
1735
def _run_test(self, test_name):
1736
test = _get_test(test_name)
1737
result = testtools.TestResult()
1741
def test_fail_has_log(self):
1742
result = self._run_test('test_fail')
1743
self.assertEqual(1, len(result.failures))
1744
result_content = result.failures[0][1]
1745
self.assertContainsRe(result_content, 'Text attachment: log')
1746
self.assertContainsRe(result_content, 'this was a failing test')
1748
def test_error_has_log(self):
1749
result = self._run_test('test_error')
1750
self.assertEqual(1, len(result.errors))
1751
result_content = result.errors[0][1]
1752
self.assertContainsRe(result_content, 'Text attachment: log')
1753
self.assertContainsRe(result_content, 'this test errored')
1755
def test_skip_has_no_log(self):
1756
result = self._run_test('test_skip')
1757
self.assertEqual(['reason'], result.skip_reasons.keys())
1758
skips = result.skip_reasons['reason']
1759
self.assertEqual(1, len(skips))
1761
self.assertFalse('log' in test.getDetails())
1763
def test_missing_feature_has_no_log(self):
1764
# testtools doesn't know about addNotSupported, so it just gets
1765
# considered as a skip
1766
result = self._run_test('test_missing_feature')
1767
self.assertEqual([missing_feature], result.skip_reasons.keys())
1768
skips = result.skip_reasons[missing_feature]
1769
self.assertEqual(1, len(skips))
1771
self.assertFalse('log' in test.getDetails())
1773
def test_xfail_has_no_log(self):
1774
result = self._run_test('test_xfail')
1775
self.assertEqual(1, len(result.expectedFailures))
1776
result_content = result.expectedFailures[0][1]
1777
self.assertNotContainsRe(result_content, 'Text attachment: log')
1778
self.assertNotContainsRe(result_content, 'test with expected failure')
1780
def test_unexpected_success_has_log(self):
1781
result = self._run_test('test_unexpected_success')
1782
self.assertEqual(1, len(result.unexpectedSuccesses))
1783
# Inconsistency, unexpectedSuccesses is a list of tests,
1784
# expectedFailures is a list of reasons?
1785
test = result.unexpectedSuccesses[0]
1786
details = test.getDetails()
1787
self.assertTrue('log' in details)
1790
class TestTestCloning(tests.TestCase):
1791
"""Tests that test cloning of TestCases (as used by multiply_tests)."""
1793
def test_cloned_testcase_does_not_share_details(self):
1794
"""A TestCase cloned with clone_test does not share mutable attributes
1795
such as details or cleanups.
1797
class Test(tests.TestCase):
1799
self.addDetail('foo', Content('text/plain', lambda: 'foo'))
1800
orig_test = Test('test_foo')
1801
cloned_test = tests.clone_test(orig_test, orig_test.id() + '(cloned)')
1802
orig_test.run(unittest.TestResult())
1803
self.assertEqual('foo', orig_test.getDetails()['foo'].iter_bytes())
1804
self.assertEqual(None, cloned_test.getDetails().get('foo'))
1806
def test_double_apply_scenario_preserves_first_scenario(self):
1807
"""Applying two levels of scenarios to a test preserves the attributes
1808
added by both scenarios.
1810
class Test(tests.TestCase):
1813
test = Test('test_foo')
1814
scenarios_x = [('x=1', {'x': 1}), ('x=2', {'x': 2})]
1815
scenarios_y = [('y=1', {'y': 1}), ('y=2', {'y': 2})]
1816
suite = tests.multiply_tests(test, scenarios_x, unittest.TestSuite())
1817
suite = tests.multiply_tests(suite, scenarios_y, unittest.TestSuite())
1818
all_tests = list(tests.iter_suite_tests(suite))
1819
self.assertLength(4, all_tests)
1820
all_xys = sorted((t.x, t.y) for t in all_tests)
1821
self.assertEqual([(1, 1), (1, 2), (2, 1), (2, 2)], all_xys)
1824
1660
# NB: Don't delete this; it's not actually from 0.11!
1825
1661
@deprecated_function(deprecated_in((0, 11, 0)))
1826
1662
def sample_deprecated_function():
2134
1973
load_list='missing file name', list_only=True)
2137
class TestSubunitLogDetails(tests.TestCase, SelfTestHelper):
2139
_test_needs_features = [features.subunit]
2141
def run_subunit_stream(self, test_name):
2142
from subunit import ProtocolTestCase
2144
return TestUtil.TestSuite([_get_test(test_name)])
2145
stream = self.run_selftest(runner_class=tests.SubUnitBzrRunner,
2146
test_suite_factory=factory)
2147
test = ProtocolTestCase(stream)
2148
result = testtools.TestResult()
2150
content = stream.getvalue()
2151
return content, result
2153
def test_fail_has_log(self):
2154
content, result = self.run_subunit_stream('test_fail')
2155
self.assertEqual(1, len(result.failures))
2156
self.assertContainsRe(content, '(?m)^log$')
2157
self.assertContainsRe(content, 'this test will fail')
2159
def test_error_has_log(self):
2160
content, result = self.run_subunit_stream('test_error')
2161
self.assertContainsRe(content, '(?m)^log$')
2162
self.assertContainsRe(content, 'this test errored')
2164
def test_skip_has_no_log(self):
2165
content, result = self.run_subunit_stream('test_skip')
2166
self.assertNotContainsRe(content, '(?m)^log$')
2167
self.assertNotContainsRe(content, 'this test will be skipped')
2168
self.assertEqual(['reason'], result.skip_reasons.keys())
2169
skips = result.skip_reasons['reason']
2170
self.assertEqual(1, len(skips))
2172
# RemotedTestCase doesn't preserve the "details"
2173
## self.assertFalse('log' in test.getDetails())
2175
def test_missing_feature_has_no_log(self):
2176
content, result = self.run_subunit_stream('test_missing_feature')
2177
self.assertNotContainsRe(content, '(?m)^log$')
2178
self.assertNotContainsRe(content, 'missing the feature')
2179
self.assertEqual(['_MissingFeature\n'], result.skip_reasons.keys())
2180
skips = result.skip_reasons['_MissingFeature\n']
2181
self.assertEqual(1, len(skips))
2183
# RemotedTestCase doesn't preserve the "details"
2184
## self.assertFalse('log' in test.getDetails())
2186
def test_xfail_has_no_log(self):
2187
content, result = self.run_subunit_stream('test_xfail')
2188
self.assertNotContainsRe(content, '(?m)^log$')
2189
self.assertNotContainsRe(content, 'test with expected failure')
2190
self.assertEqual(1, len(result.expectedFailures))
2191
result_content = result.expectedFailures[0][1]
2192
self.assertNotContainsRe(result_content, 'Text attachment: log')
2193
self.assertNotContainsRe(result_content, 'test with expected failure')
2195
def test_unexpected_success_has_log(self):
2196
content, result = self.run_subunit_stream('test_unexpected_success')
2197
self.assertContainsRe(content, '(?m)^log$')
2198
self.assertContainsRe(content, 'test with unexpected success')
2199
# GZ 2011-05-18: Old versions of subunit treat unexpected success as a
2200
# success, if a min version check is added remove this
2201
from subunit import TestProtocolClient as _Client
2202
if _Client.addUnexpectedSuccess.im_func is _Client.addSuccess.im_func:
2203
self.expectFailure('subunit treats "unexpectedSuccess"'
2204
' as a plain success',
2205
self.assertEqual, 1, len(result.unexpectedSuccesses))
2206
self.assertEqual(1, len(result.unexpectedSuccesses))
2207
test = result.unexpectedSuccesses[0]
2208
# RemotedTestCase doesn't preserve the "details"
2209
## self.assertTrue('log' in test.getDetails())
2211
def test_success_has_no_log(self):
2212
content, result = self.run_subunit_stream('test_success')
2213
self.assertEqual(1, result.testsRun)
2214
self.assertNotContainsRe(content, '(?m)^log$')
2215
self.assertNotContainsRe(content, 'this test succeeds')
2218
1976
class TestRunBzr(tests.TestCase):
2534
2285
def test_allow_plugins(self):
2535
2286
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2537
2288
command = self._popen_args[0]
2538
2289
self.assertEqual([], command[2:])
2540
2291
def test_set_env(self):
2541
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2292
self.failIf('EXISTANT_ENV_VAR' in os.environ)
2542
2293
# set in the child
2543
2294
def check_environment():
2544
2295
self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR'])
2545
2296
self.check_popen_state = check_environment
2546
2297
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2547
env_changes={'EXISTANT_ENV_VAR':'set variable'})
2298
env_changes={'EXISTANT_ENV_VAR':'set variable'})
2548
2299
# not set in theparent
2549
2300
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2551
2302
def test_run_bzr_subprocess_env_del(self):
2552
2303
"""run_bzr_subprocess can remove environment variables too."""
2553
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2304
self.failIf('EXISTANT_ENV_VAR' in os.environ)
2554
2305
def check_environment():
2555
2306
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2556
2307
os.environ['EXISTANT_ENV_VAR'] = 'set variable'
2557
2308
self.check_popen_state = check_environment
2558
2309
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2559
env_changes={'EXISTANT_ENV_VAR':None})
2310
env_changes={'EXISTANT_ENV_VAR':None})
2560
2311
# Still set in parent
2561
2312
self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR'])
2562
2313
del os.environ['EXISTANT_ENV_VAR']
2564
2315
def test_env_del_missing(self):
2565
self.assertFalse('NON_EXISTANT_ENV_VAR' in os.environ)
2316
self.failIf('NON_EXISTANT_ENV_VAR' in os.environ)
2566
2317
def check_environment():
2567
2318
self.assertFalse('NON_EXISTANT_ENV_VAR' in os.environ)
2568
2319
self.check_popen_state = check_environment
2569
2320
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2570
env_changes={'NON_EXISTANT_ENV_VAR':None})
2321
env_changes={'NON_EXISTANT_ENV_VAR':None})
2572
2323
def test_working_dir(self):
2573
2324
"""Test that we can specify the working dir for the child"""
3211
2953
self.assertEquals('bzrlib.plugins', tpr.resolve_alias('bp'))
3214
class TestThreadLeakDetection(tests.TestCase):
3215
"""Ensure when tests leak threads we detect and report it"""
3217
class LeakRecordingResult(tests.ExtendedTestResult):
3219
tests.ExtendedTestResult.__init__(self, StringIO(), 0, 1)
3221
def _report_thread_leak(self, test, leaks, alive):
3222
self.leaks.append((test, leaks))
3224
def test_testcase_without_addCleanups(self):
3225
"""Check old TestCase instances don't break with leak detection"""
3226
class Test(unittest.TestCase):
3229
result = self.LeakRecordingResult()
3231
result.startTestRun()
3233
result.stopTestRun()
3234
self.assertEqual(result._tests_leaking_threads_count, 0)
3235
self.assertEqual(result.leaks, [])
3237
def test_thread_leak(self):
3238
"""Ensure a thread that outlives the running of a test is reported
3240
Uses a thread that blocks on an event, and is started by the inner
3241
test case. As the thread outlives the inner case's run, it should be
3242
detected as a leak, but the event is then set so that the thread can
3243
be safely joined in cleanup so it's not leaked for real.
3245
event = threading.Event()
3246
thread = threading.Thread(name="Leaker", target=event.wait)
3247
class Test(tests.TestCase):
3248
def test_leak(self):
3250
result = self.LeakRecordingResult()
3251
test = Test("test_leak")
3252
self.addCleanup(thread.join)
3253
self.addCleanup(event.set)
3254
result.startTestRun()
3256
result.stopTestRun()
3257
self.assertEqual(result._tests_leaking_threads_count, 1)
3258
self.assertEqual(result._first_thread_leaker_id, test.id())
3259
self.assertEqual(result.leaks, [(test, set([thread]))])
3260
self.assertContainsString(result.stream.getvalue(), "leaking threads")
3262
def test_multiple_leaks(self):
3263
"""Check multiple leaks are blamed on the test cases at fault
3265
Same concept as the previous test, but has one inner test method that
3266
leaks two threads, and one that doesn't leak at all.
3268
event = threading.Event()
3269
thread_a = threading.Thread(name="LeakerA", target=event.wait)
3270
thread_b = threading.Thread(name="LeakerB", target=event.wait)
3271
thread_c = threading.Thread(name="LeakerC", target=event.wait)
3272
class Test(tests.TestCase):
3273
def test_first_leak(self):
3275
def test_second_no_leak(self):
3277
def test_third_leak(self):
3280
result = self.LeakRecordingResult()
3281
first_test = Test("test_first_leak")
3282
third_test = Test("test_third_leak")
3283
self.addCleanup(thread_a.join)
3284
self.addCleanup(thread_b.join)
3285
self.addCleanup(thread_c.join)
3286
self.addCleanup(event.set)
3287
result.startTestRun()
3289
[first_test, Test("test_second_no_leak"), third_test]
3291
result.stopTestRun()
3292
self.assertEqual(result._tests_leaking_threads_count, 2)
3293
self.assertEqual(result._first_thread_leaker_id, first_test.id())
3294
self.assertEqual(result.leaks, [
3295
(first_test, set([thread_b])),
3296
(third_test, set([thread_a, thread_c]))])
3297
self.assertContainsString(result.stream.getvalue(), "leaking threads")
3300
class TestPostMortemDebugging(tests.TestCase):
3301
"""Check post mortem debugging works when tests fail or error"""
3303
class TracebackRecordingResult(tests.ExtendedTestResult):
3305
tests.ExtendedTestResult.__init__(self, StringIO(), 0, 1)
3306
self.postcode = None
3307
def _post_mortem(self, tb=None):
3308
"""Record the code object at the end of the current traceback"""
3309
tb = tb or sys.exc_info()[2]
3312
while next is not None:
3315
self.postcode = tb.tb_frame.f_code
3316
def report_error(self, test, err):
3318
def report_failure(self, test, err):
3321
def test_location_unittest_error(self):
3322
"""Needs right post mortem traceback with erroring unittest case"""
3323
class Test(unittest.TestCase):
3326
result = self.TracebackRecordingResult()
3328
self.assertEqual(result.postcode, Test.runTest.func_code)
3330
def test_location_unittest_failure(self):
3331
"""Needs right post mortem traceback with failing unittest case"""
3332
class Test(unittest.TestCase):
3334
raise self.failureException
3335
result = self.TracebackRecordingResult()
3337
self.assertEqual(result.postcode, Test.runTest.func_code)
3339
def test_location_bt_error(self):
3340
"""Needs right post mortem traceback with erroring bzrlib.tests case"""
3341
class Test(tests.TestCase):
3342
def test_error(self):
3344
result = self.TracebackRecordingResult()
3345
Test("test_error").run(result)
3346
self.assertEqual(result.postcode, Test.test_error.func_code)
3348
def test_location_bt_failure(self):
3349
"""Needs right post mortem traceback with failing bzrlib.tests case"""
3350
class Test(tests.TestCase):
3351
def test_failure(self):
3352
raise self.failureException
3353
result = self.TracebackRecordingResult()
3354
Test("test_failure").run(result)
3355
self.assertEqual(result.postcode, Test.test_failure.func_code)
3357
def test_env_var_triggers_post_mortem(self):
3358
"""Check pdb.post_mortem is called iff BZR_TEST_PDB is set"""
3360
result = tests.ExtendedTestResult(StringIO(), 0, 1)
3361
post_mortem_calls = []
3362
self.overrideAttr(pdb, "post_mortem", post_mortem_calls.append)
3363
self.overrideEnv('BZR_TEST_PDB', None)
3364
result._post_mortem(1)
3365
self.overrideEnv('BZR_TEST_PDB', 'on')
3366
result._post_mortem(2)
3367
self.assertEqual([2], post_mortem_calls)
3370
2956
class TestRunSuite(tests.TestCase):
3372
2958
def test_runner_class(self):
3383
2969
self.verbosity)
3384
2970
tests.run_suite(suite, runner_class=MyRunner, stream=StringIO())
3385
2971
self.assertLength(1, calls)
3388
class TestEnvironHandling(tests.TestCase):
3390
def test_overrideEnv_None_called_twice_doesnt_leak(self):
3391
self.assertFalse('MYVAR' in os.environ)
3392
self.overrideEnv('MYVAR', '42')
3393
# We use an embedded test to make sure we fix the _captureVar bug
3394
class Test(tests.TestCase):
3396
# The first call save the 42 value
3397
self.overrideEnv('MYVAR', None)
3398
self.assertEquals(None, os.environ.get('MYVAR'))
3399
# Make sure we can call it twice
3400
self.overrideEnv('MYVAR', None)
3401
self.assertEquals(None, os.environ.get('MYVAR'))
3403
result = tests.TextTestResult(output, 0, 1)
3404
Test('test_me').run(result)
3405
if not result.wasStrictlySuccessful():
3406
self.fail(output.getvalue())
3407
# We get our value back
3408
self.assertEquals('42', os.environ.get('MYVAR'))
3411
class TestIsolatedEnv(tests.TestCase):
3412
"""Test isolating tests from os.environ.
3414
Since we use tests that are already isolated from os.environ a bit of care
3415
should be taken when designing the tests to avoid bootstrap side-effects.
3416
The tests start an already clean os.environ which allow doing valid
3417
assertions about which variables are present or not and design tests around
3421
class ScratchMonkey(tests.TestCase):
3426
def test_basics(self):
3427
# Make sure we know the definition of BZR_HOME: not part of os.environ
3428
# for tests.TestCase.
3429
self.assertTrue('BZR_HOME' in tests.isolated_environ)
3430
self.assertEquals(None, tests.isolated_environ['BZR_HOME'])
3431
# Being part of isolated_environ, BZR_HOME should not appear here
3432
self.assertFalse('BZR_HOME' in os.environ)
3433
# Make sure we know the definition of LINES: part of os.environ for
3435
self.assertTrue('LINES' in tests.isolated_environ)
3436
self.assertEquals('25', tests.isolated_environ['LINES'])
3437
self.assertEquals('25', os.environ['LINES'])
3439
def test_injecting_unknown_variable(self):
3440
# BZR_HOME is known to be absent from os.environ
3441
test = self.ScratchMonkey('test_me')
3442
tests.override_os_environ(test, {'BZR_HOME': 'foo'})
3443
self.assertEquals('foo', os.environ['BZR_HOME'])
3444
tests.restore_os_environ(test)
3445
self.assertFalse('BZR_HOME' in os.environ)
3447
def test_injecting_known_variable(self):
3448
test = self.ScratchMonkey('test_me')
3449
# LINES is known to be present in os.environ
3450
tests.override_os_environ(test, {'LINES': '42'})
3451
self.assertEquals('42', os.environ['LINES'])
3452
tests.restore_os_environ(test)
3453
self.assertEquals('25', os.environ['LINES'])
3455
def test_deleting_variable(self):
3456
test = self.ScratchMonkey('test_me')
3457
# LINES is known to be present in os.environ
3458
tests.override_os_environ(test, {'LINES': None})
3459
self.assertTrue('LINES' not in os.environ)
3460
tests.restore_os_environ(test)
3461
self.assertEquals('25', os.environ['LINES'])
3464
class TestDocTestSuiteIsolation(tests.TestCase):
3465
"""Test that `tests.DocTestSuite` isolates doc tests from os.environ.
3467
Since tests.TestCase alreay provides an isolation from os.environ, we use
3468
the clean environment as a base for testing. To precisely capture the
3469
isolation provided by tests.DocTestSuite, we use doctest.DocTestSuite to
3472
We want to make sure `tests.DocTestSuite` respect `tests.isolated_environ`,
3473
not `os.environ` so each test overrides it to suit its needs.
3477
def get_doctest_suite_for_string(self, klass, string):
3478
class Finder(doctest.DocTestFinder):
3480
def find(*args, **kwargs):
3481
test = doctest.DocTestParser().get_doctest(
3482
string, {}, 'foo', 'foo.py', 0)
3485
suite = klass(test_finder=Finder())
3488
def run_doctest_suite_for_string(self, klass, string):
3489
suite = self.get_doctest_suite_for_string(klass, string)
3491
result = tests.TextTestResult(output, 0, 1)
3493
return result, output
3495
def assertDocTestStringSucceds(self, klass, string):
3496
result, output = self.run_doctest_suite_for_string(klass, string)
3497
if not result.wasStrictlySuccessful():
3498
self.fail(output.getvalue())
3500
def assertDocTestStringFails(self, klass, string):
3501
result, output = self.run_doctest_suite_for_string(klass, string)
3502
if result.wasStrictlySuccessful():
3503
self.fail(output.getvalue())
3505
def test_injected_variable(self):
3506
self.overrideAttr(tests, 'isolated_environ', {'LINES': '42'})
3509
>>> os.environ['LINES']
3512
# doctest.DocTestSuite fails as it sees '25'
3513
self.assertDocTestStringFails(doctest.DocTestSuite, test)
3514
# tests.DocTestSuite sees '42'
3515
self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
3517
def test_deleted_variable(self):
3518
self.overrideAttr(tests, 'isolated_environ', {'LINES': None})
3521
>>> os.environ.get('LINES')
3523
# doctest.DocTestSuite fails as it sees '25'
3524
self.assertDocTestStringFails(doctest.DocTestSuite, test)
3525
# tests.DocTestSuite sees None
3526
self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
3529
class TestSelftestExcludePatterns(tests.TestCase):
3532
super(TestSelftestExcludePatterns, self).setUp()
3533
self.overrideAttr(tests, 'test_suite', self.suite_factory)
3535
def suite_factory(self, keep_only=None, starting_with=None):
3536
"""A test suite factory with only a few tests."""
3537
class Test(tests.TestCase):
3539
# We don't need the full class path
3540
return self._testMethodName
3547
return TestUtil.TestSuite([Test("a"), Test("b"), Test("c")])
3549
def assertTestList(self, expected, *selftest_args):
3550
# We rely on setUp installing the right test suite factory so we can
3551
# test at the command level without loading the whole test suite
3552
out, err = self.run_bzr(('selftest', '--list') + selftest_args)
3553
actual = out.splitlines()
3554
self.assertEquals(expected, actual)
3556
def test_full_list(self):
3557
self.assertTestList(['a', 'b', 'c'])
3559
def test_single_exclude(self):
3560
self.assertTestList(['b', 'c'], '-x', 'a')
3562
def test_mutiple_excludes(self):
3563
self.assertTestList(['c'], '-x', 'a', '-x', 'b')
3566
class TestCounterHooks(tests.TestCase, SelfTestHelper):
3568
_test_needs_features = [features.subunit]
3571
super(TestCounterHooks, self).setUp()
3572
class Test(tests.TestCase):
3575
super(Test, self).setUp()
3576
self.hooks = hooks.Hooks()
3577
self.hooks.add_hook('myhook', 'Foo bar blah', (2,4))
3578
self.install_counter_hook(self.hooks, 'myhook')
3583
def run_hook_once(self):
3584
for hook in self.hooks['myhook']:
3587
self.test_class = Test
3589
def assertHookCalls(self, expected_calls, test_name):
3590
test = self.test_class(test_name)
3591
result = unittest.TestResult()
3593
self.assertTrue(hasattr(test, '_counters'))
3594
self.assertTrue(test._counters.has_key('myhook'))
3595
self.assertEquals(expected_calls, test._counters['myhook'])
3597
def test_no_hook(self):
3598
self.assertHookCalls(0, 'no_hook')
3600
def test_run_hook_once(self):
3601
tt = features.testtools
3602
if tt.module.__version__ < (0, 9, 8):
3603
raise tests.TestSkipped('testtools-0.9.8 required for addDetail')
3604
self.assertHookCalls(1, 'run_hook_once')