750
764
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
767
def _time_hello_world_encoding(self):
794
768
"""Profile two sleep calls
835
809
self.assertContainsRe(output,
836
810
r"LSProf output for <type 'unicode'>\(\('world',\), {'errors': 'replace'}\)\n")
812
def test_uses_time_from_testtools(self):
813
"""Test case timings in verbose results should use testtools times"""
815
class TimeAddedVerboseTestResult(tests.VerboseTestResult):
816
def startTest(self, test):
817
self.time(datetime.datetime.utcfromtimestamp(1.145))
818
super(TimeAddedVerboseTestResult, self).startTest(test)
819
def addSuccess(self, test):
820
self.time(datetime.datetime.utcfromtimestamp(51.147))
821
super(TimeAddedVerboseTestResult, self).addSuccess(test)
822
def report_tests_starting(self): pass
824
self.get_passing_test().run(TimeAddedVerboseTestResult(sio, 0, 2))
825
self.assertEndsWith(sio.getvalue(), "OK 50002ms\n")
838
827
def test_known_failure(self):
839
828
"""A KnownFailure being raised should trigger several result actions."""
840
829
class InstrumentedTestResult(tests.ExtendedTestResult):
841
830
def stopTestRun(self): pass
842
def startTests(self): pass
843
def report_test_start(self, test): pass
831
def report_tests_starting(self): pass
844
832
def report_known_failure(self, test, err=None, details=None):
845
833
self._call = test, 'known failure'
846
834
result = InstrumentedTestResult(None, None, None, None)
1193
def _patch_get_bzr_source_tree(self):
1194
# Reading from the actual source tree breaks isolation, but we don't
1195
# want to assume that thats *all* that would happen.
1196
self._get_source_tree_calls = []
1198
self._get_source_tree_calls.append("called")
1200
self.overrideAttr(bzrlib.version, '_get_bzr_source_tree', new_get)
1202
def test_bench_history(self):
1203
# tests that the running the benchmark passes bench_history into
1204
# the test result object. We can tell that happens if
1205
# _get_bzr_source_tree is called.
1206
self._patch_get_bzr_source_tree()
1207
test = TestRunner('dummy_test')
1209
runner = tests.TextTestRunner(stream=self._log_file,
1210
bench_history=output)
1211
result = self.run_test_runner(runner, test)
1212
output_string = output.getvalue()
1213
self.assertContainsRe(output_string, "--date [0-9.]+")
1214
self.assertLength(1, self._get_source_tree_calls)
1214
def test_verbose_test_count(self):
1215
"""A verbose test run reports the right test count at the start"""
1216
suite = TestUtil.TestSuite([
1217
unittest.FunctionTestCase(lambda:None),
1218
unittest.FunctionTestCase(lambda:None)])
1219
self.assertEqual(suite.countTestCases(), 2)
1221
runner = tests.TextTestRunner(stream=stream, verbosity=2)
1222
# Need to use the CountingDecorator as that's what sets num_tests
1223
result = self.run_test_runner(runner, tests.CountingDecorator(suite))
1224
self.assertStartsWith(stream.getvalue(), "running 2 tests")
1216
1226
def test_startTestRun(self):
1217
1227
"""run should call result.startTestRun()"""
1219
class LoggingDecorator(tests.ForwardingResult):
1229
class LoggingDecorator(ExtendedToOriginalDecorator):
1220
1230
def startTestRun(self):
1221
tests.ForwardingResult.startTestRun(self)
1231
ExtendedToOriginalDecorator.startTestRun(self)
1222
1232
calls.append('startTestRun')
1223
1233
test = unittest.FunctionTestCase(lambda:None)
1224
1234
stream = StringIO()
1654
1684
test.run(unittest.TestResult())
1655
1685
self.assertEqual('original', obj.test_attr)
1687
def test_recordCalls(self):
1688
from bzrlib.tests import test_selftest
1689
calls = self.recordCalls(
1690
test_selftest, '_add_numbers')
1691
self.assertEqual(test_selftest._add_numbers(2, 10),
1693
self.assertEquals(calls, [((2, 10), {})])
1696
def _add_numbers(a, b):
1700
class _MissingFeature(features.Feature):
1703
missing_feature = _MissingFeature()
1706
def _get_test(name):
1707
"""Get an instance of a specific example test.
1709
We protect this in a function so that they don't auto-run in the test
1713
class ExampleTests(tests.TestCase):
1715
def test_fail(self):
1716
mutter('this was a failing test')
1717
self.fail('this test will fail')
1719
def test_error(self):
1720
mutter('this test errored')
1721
raise RuntimeError('gotcha')
1723
def test_missing_feature(self):
1724
mutter('missing the feature')
1725
self.requireFeature(missing_feature)
1727
def test_skip(self):
1728
mutter('this test will be skipped')
1729
raise tests.TestSkipped('reason')
1731
def test_success(self):
1732
mutter('this test succeeds')
1734
def test_xfail(self):
1735
mutter('test with expected failure')
1736
self.knownFailure('this_fails')
1738
def test_unexpected_success(self):
1739
mutter('test with unexpected success')
1740
self.expectFailure('should_fail', lambda: None)
1742
return ExampleTests(name)
1745
class TestTestCaseLogDetails(tests.TestCase):
1747
def _run_test(self, test_name):
1748
test = _get_test(test_name)
1749
result = testtools.TestResult()
1753
def test_fail_has_log(self):
1754
result = self._run_test('test_fail')
1755
self.assertEqual(1, len(result.failures))
1756
result_content = result.failures[0][1]
1757
if testtools_version < (0, 9, 12):
1758
self.assertContainsRe(result_content, 'Text attachment: log')
1759
self.assertContainsRe(result_content, 'this was a failing test')
1761
def test_error_has_log(self):
1762
result = self._run_test('test_error')
1763
self.assertEqual(1, len(result.errors))
1764
result_content = result.errors[0][1]
1765
if testtools_version < (0, 9, 12):
1766
self.assertContainsRe(result_content, 'Text attachment: log')
1767
self.assertContainsRe(result_content, 'this test errored')
1769
def test_skip_has_no_log(self):
1770
result = self._run_test('test_skip')
1771
self.assertEqual(['reason'], result.skip_reasons.keys())
1772
skips = result.skip_reasons['reason']
1773
self.assertEqual(1, len(skips))
1775
self.assertFalse('log' in test.getDetails())
1777
def test_missing_feature_has_no_log(self):
1778
# testtools doesn't know about addNotSupported, so it just gets
1779
# considered as a skip
1780
result = self._run_test('test_missing_feature')
1781
self.assertEqual([missing_feature], result.skip_reasons.keys())
1782
skips = result.skip_reasons[missing_feature]
1783
self.assertEqual(1, len(skips))
1785
self.assertFalse('log' in test.getDetails())
1787
def test_xfail_has_no_log(self):
1788
result = self._run_test('test_xfail')
1789
self.assertEqual(1, len(result.expectedFailures))
1790
result_content = result.expectedFailures[0][1]
1791
self.assertNotContainsRe(result_content, 'Text attachment: log')
1792
self.assertNotContainsRe(result_content, 'test with expected failure')
1794
def test_unexpected_success_has_log(self):
1795
result = self._run_test('test_unexpected_success')
1796
self.assertEqual(1, len(result.unexpectedSuccesses))
1797
# Inconsistency, unexpectedSuccesses is a list of tests,
1798
# expectedFailures is a list of reasons?
1799
test = result.unexpectedSuccesses[0]
1800
details = test.getDetails()
1801
self.assertTrue('log' in details)
1804
class TestTestCloning(tests.TestCase):
1805
"""Tests that test cloning of TestCases (as used by multiply_tests)."""
1807
def test_cloned_testcase_does_not_share_details(self):
1808
"""A TestCase cloned with clone_test does not share mutable attributes
1809
such as details or cleanups.
1811
class Test(tests.TestCase):
1813
self.addDetail('foo', Content('text/plain', lambda: 'foo'))
1814
orig_test = Test('test_foo')
1815
cloned_test = tests.clone_test(orig_test, orig_test.id() + '(cloned)')
1816
orig_test.run(unittest.TestResult())
1817
self.assertEqual('foo', orig_test.getDetails()['foo'].iter_bytes())
1818
self.assertEqual(None, cloned_test.getDetails().get('foo'))
1820
def test_double_apply_scenario_preserves_first_scenario(self):
1821
"""Applying two levels of scenarios to a test preserves the attributes
1822
added by both scenarios.
1824
class Test(tests.TestCase):
1827
test = Test('test_foo')
1828
scenarios_x = [('x=1', {'x': 1}), ('x=2', {'x': 2})]
1829
scenarios_y = [('y=1', {'y': 1}), ('y=2', {'y': 2})]
1830
suite = tests.multiply_tests(test, scenarios_x, unittest.TestSuite())
1831
suite = tests.multiply_tests(suite, scenarios_y, unittest.TestSuite())
1832
all_tests = list(tests.iter_suite_tests(suite))
1833
self.assertLength(4, all_tests)
1834
all_xys = sorted((t.x, t.y) for t in all_tests)
1835
self.assertEqual([(1, 1), (1, 2), (2, 1), (2, 2)], all_xys)
1658
1838
# NB: Don't delete this; it's not actually from 0.11!
1659
1839
@deprecated_function(deprecated_in((0, 11, 0)))
1971
2148
load_list='missing file name', list_only=True)
2151
class TestSubunitLogDetails(tests.TestCase, SelfTestHelper):
2153
_test_needs_features = [features.subunit]
2155
def run_subunit_stream(self, test_name):
2156
from subunit import ProtocolTestCase
2158
return TestUtil.TestSuite([_get_test(test_name)])
2159
stream = self.run_selftest(runner_class=tests.SubUnitBzrRunner,
2160
test_suite_factory=factory)
2161
test = ProtocolTestCase(stream)
2162
result = testtools.TestResult()
2164
content = stream.getvalue()
2165
return content, result
2167
def test_fail_has_log(self):
2168
content, result = self.run_subunit_stream('test_fail')
2169
self.assertEqual(1, len(result.failures))
2170
self.assertContainsRe(content, '(?m)^log$')
2171
self.assertContainsRe(content, 'this test will fail')
2173
def test_error_has_log(self):
2174
content, result = self.run_subunit_stream('test_error')
2175
self.assertContainsRe(content, '(?m)^log$')
2176
self.assertContainsRe(content, 'this test errored')
2178
def test_skip_has_no_log(self):
2179
content, result = self.run_subunit_stream('test_skip')
2180
self.assertNotContainsRe(content, '(?m)^log$')
2181
self.assertNotContainsRe(content, 'this test will be skipped')
2182
self.assertEqual(['reason'], result.skip_reasons.keys())
2183
skips = result.skip_reasons['reason']
2184
self.assertEqual(1, len(skips))
2186
# RemotedTestCase doesn't preserve the "details"
2187
## self.assertFalse('log' in test.getDetails())
2189
def test_missing_feature_has_no_log(self):
2190
content, result = self.run_subunit_stream('test_missing_feature')
2191
self.assertNotContainsRe(content, '(?m)^log$')
2192
self.assertNotContainsRe(content, 'missing the feature')
2193
self.assertEqual(['_MissingFeature\n'], result.skip_reasons.keys())
2194
skips = result.skip_reasons['_MissingFeature\n']
2195
self.assertEqual(1, len(skips))
2197
# RemotedTestCase doesn't preserve the "details"
2198
## self.assertFalse('log' in test.getDetails())
2200
def test_xfail_has_no_log(self):
2201
content, result = self.run_subunit_stream('test_xfail')
2202
self.assertNotContainsRe(content, '(?m)^log$')
2203
self.assertNotContainsRe(content, 'test with expected failure')
2204
self.assertEqual(1, len(result.expectedFailures))
2205
result_content = result.expectedFailures[0][1]
2206
self.assertNotContainsRe(result_content, 'Text attachment: log')
2207
self.assertNotContainsRe(result_content, 'test with expected failure')
2209
def test_unexpected_success_has_log(self):
2210
content, result = self.run_subunit_stream('test_unexpected_success')
2211
self.assertContainsRe(content, '(?m)^log$')
2212
self.assertContainsRe(content, 'test with unexpected success')
2213
# GZ 2011-05-18: Old versions of subunit treat unexpected success as a
2214
# success, if a min version check is added remove this
2215
from subunit import TestProtocolClient as _Client
2216
if _Client.addUnexpectedSuccess.im_func is _Client.addSuccess.im_func:
2217
self.expectFailure('subunit treats "unexpectedSuccess"'
2218
' as a plain success',
2219
self.assertEqual, 1, len(result.unexpectedSuccesses))
2220
self.assertEqual(1, len(result.unexpectedSuccesses))
2221
test = result.unexpectedSuccesses[0]
2222
# RemotedTestCase doesn't preserve the "details"
2223
## self.assertTrue('log' in test.getDetails())
2225
def test_success_has_no_log(self):
2226
content, result = self.run_subunit_stream('test_success')
2227
self.assertEqual(1, result.testsRun)
2228
self.assertNotContainsRe(content, '(?m)^log$')
2229
self.assertNotContainsRe(content, 'this test succeeds')
1974
2232
class TestRunBzr(tests.TestCase):
2283
2548
def test_allow_plugins(self):
2284
2549
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2286
2551
command = self._popen_args[0]
2287
2552
self.assertEqual([], command[2:])
2289
2554
def test_set_env(self):
2290
self.failIf('EXISTANT_ENV_VAR' in os.environ)
2555
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2291
2556
# set in the child
2292
2557
def check_environment():
2293
2558
self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR'])
2294
2559
self.check_popen_state = check_environment
2295
2560
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2296
env_changes={'EXISTANT_ENV_VAR':'set variable'})
2561
env_changes={'EXISTANT_ENV_VAR':'set variable'})
2297
2562
# not set in theparent
2298
2563
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2300
2565
def test_run_bzr_subprocess_env_del(self):
2301
2566
"""run_bzr_subprocess can remove environment variables too."""
2302
self.failIf('EXISTANT_ENV_VAR' in os.environ)
2567
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2303
2568
def check_environment():
2304
2569
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2305
2570
os.environ['EXISTANT_ENV_VAR'] = 'set variable'
2306
2571
self.check_popen_state = check_environment
2307
2572
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2308
env_changes={'EXISTANT_ENV_VAR':None})
2573
env_changes={'EXISTANT_ENV_VAR':None})
2309
2574
# Still set in parent
2310
2575
self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR'])
2311
2576
del os.environ['EXISTANT_ENV_VAR']
2313
2578
def test_env_del_missing(self):
2314
self.failIf('NON_EXISTANT_ENV_VAR' in os.environ)
2579
self.assertFalse('NON_EXISTANT_ENV_VAR' in os.environ)
2315
2580
def check_environment():
2316
2581
self.assertFalse('NON_EXISTANT_ENV_VAR' in os.environ)
2317
2582
self.check_popen_state = check_environment
2318
2583
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2319
env_changes={'NON_EXISTANT_ENV_VAR':None})
2584
env_changes={'NON_EXISTANT_ENV_VAR':None})
2321
2586
def test_working_dir(self):
2322
2587
"""Test that we can specify the working dir for the child"""
2357
2621
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)
2434
2624
class TestSelftestFiltering(tests.TestCase):
2436
2626
def setUp(self):
2960
3151
self.assertEquals('bzrlib.plugins', tpr.resolve_alias('bp'))
3154
class TestThreadLeakDetection(tests.TestCase):
3155
"""Ensure when tests leak threads we detect and report it"""
3157
class LeakRecordingResult(tests.ExtendedTestResult):
3159
tests.ExtendedTestResult.__init__(self, StringIO(), 0, 1)
3161
def _report_thread_leak(self, test, leaks, alive):
3162
self.leaks.append((test, leaks))
3164
def test_testcase_without_addCleanups(self):
3165
"""Check old TestCase instances don't break with leak detection"""
3166
class Test(unittest.TestCase):
3169
result = self.LeakRecordingResult()
3171
result.startTestRun()
3173
result.stopTestRun()
3174
self.assertEqual(result._tests_leaking_threads_count, 0)
3175
self.assertEqual(result.leaks, [])
3177
def test_thread_leak(self):
3178
"""Ensure a thread that outlives the running of a test is reported
3180
Uses a thread that blocks on an event, and is started by the inner
3181
test case. As the thread outlives the inner case's run, it should be
3182
detected as a leak, but the event is then set so that the thread can
3183
be safely joined in cleanup so it's not leaked for real.
3185
event = threading.Event()
3186
thread = threading.Thread(name="Leaker", target=event.wait)
3187
class Test(tests.TestCase):
3188
def test_leak(self):
3190
result = self.LeakRecordingResult()
3191
test = Test("test_leak")
3192
self.addCleanup(thread.join)
3193
self.addCleanup(event.set)
3194
result.startTestRun()
3196
result.stopTestRun()
3197
self.assertEqual(result._tests_leaking_threads_count, 1)
3198
self.assertEqual(result._first_thread_leaker_id, test.id())
3199
self.assertEqual(result.leaks, [(test, set([thread]))])
3200
self.assertContainsString(result.stream.getvalue(), "leaking threads")
3202
def test_multiple_leaks(self):
3203
"""Check multiple leaks are blamed on the test cases at fault
3205
Same concept as the previous test, but has one inner test method that
3206
leaks two threads, and one that doesn't leak at all.
3208
event = threading.Event()
3209
thread_a = threading.Thread(name="LeakerA", target=event.wait)
3210
thread_b = threading.Thread(name="LeakerB", target=event.wait)
3211
thread_c = threading.Thread(name="LeakerC", target=event.wait)
3212
class Test(tests.TestCase):
3213
def test_first_leak(self):
3215
def test_second_no_leak(self):
3217
def test_third_leak(self):
3220
result = self.LeakRecordingResult()
3221
first_test = Test("test_first_leak")
3222
third_test = Test("test_third_leak")
3223
self.addCleanup(thread_a.join)
3224
self.addCleanup(thread_b.join)
3225
self.addCleanup(thread_c.join)
3226
self.addCleanup(event.set)
3227
result.startTestRun()
3229
[first_test, Test("test_second_no_leak"), third_test]
3231
result.stopTestRun()
3232
self.assertEqual(result._tests_leaking_threads_count, 2)
3233
self.assertEqual(result._first_thread_leaker_id, first_test.id())
3234
self.assertEqual(result.leaks, [
3235
(first_test, set([thread_b])),
3236
(third_test, set([thread_a, thread_c]))])
3237
self.assertContainsString(result.stream.getvalue(), "leaking threads")
3240
class TestPostMortemDebugging(tests.TestCase):
3241
"""Check post mortem debugging works when tests fail or error"""
3243
class TracebackRecordingResult(tests.ExtendedTestResult):
3245
tests.ExtendedTestResult.__init__(self, StringIO(), 0, 1)
3246
self.postcode = None
3247
def _post_mortem(self, tb=None):
3248
"""Record the code object at the end of the current traceback"""
3249
tb = tb or sys.exc_info()[2]
3252
while next is not None:
3255
self.postcode = tb.tb_frame.f_code
3256
def report_error(self, test, err):
3258
def report_failure(self, test, err):
3261
def test_location_unittest_error(self):
3262
"""Needs right post mortem traceback with erroring unittest case"""
3263
class Test(unittest.TestCase):
3266
result = self.TracebackRecordingResult()
3268
self.assertEqual(result.postcode, Test.runTest.func_code)
3270
def test_location_unittest_failure(self):
3271
"""Needs right post mortem traceback with failing unittest case"""
3272
class Test(unittest.TestCase):
3274
raise self.failureException
3275
result = self.TracebackRecordingResult()
3277
self.assertEqual(result.postcode, Test.runTest.func_code)
3279
def test_location_bt_error(self):
3280
"""Needs right post mortem traceback with erroring bzrlib.tests case"""
3281
class Test(tests.TestCase):
3282
def test_error(self):
3284
result = self.TracebackRecordingResult()
3285
Test("test_error").run(result)
3286
self.assertEqual(result.postcode, Test.test_error.func_code)
3288
def test_location_bt_failure(self):
3289
"""Needs right post mortem traceback with failing bzrlib.tests case"""
3290
class Test(tests.TestCase):
3291
def test_failure(self):
3292
raise self.failureException
3293
result = self.TracebackRecordingResult()
3294
Test("test_failure").run(result)
3295
self.assertEqual(result.postcode, Test.test_failure.func_code)
3297
def test_env_var_triggers_post_mortem(self):
3298
"""Check pdb.post_mortem is called iff BZR_TEST_PDB is set"""
3300
result = tests.ExtendedTestResult(StringIO(), 0, 1)
3301
post_mortem_calls = []
3302
self.overrideAttr(pdb, "post_mortem", post_mortem_calls.append)
3303
self.overrideEnv('BZR_TEST_PDB', None)
3304
result._post_mortem(1)
3305
self.overrideEnv('BZR_TEST_PDB', 'on')
3306
result._post_mortem(2)
3307
self.assertEqual([2], post_mortem_calls)
2963
3310
class TestRunSuite(tests.TestCase):
2965
3312
def test_runner_class(self):
2976
3323
self.verbosity)
2977
3324
tests.run_suite(suite, runner_class=MyRunner, stream=StringIO())
2978
3325
self.assertLength(1, calls)
3328
class TestEnvironHandling(tests.TestCase):
3330
def test_overrideEnv_None_called_twice_doesnt_leak(self):
3331
self.assertFalse('MYVAR' in os.environ)
3332
self.overrideEnv('MYVAR', '42')
3333
# We use an embedded test to make sure we fix the _captureVar bug
3334
class Test(tests.TestCase):
3336
# The first call save the 42 value
3337
self.overrideEnv('MYVAR', None)
3338
self.assertEquals(None, os.environ.get('MYVAR'))
3339
# Make sure we can call it twice
3340
self.overrideEnv('MYVAR', None)
3341
self.assertEquals(None, os.environ.get('MYVAR'))
3343
result = tests.TextTestResult(output, 0, 1)
3344
Test('test_me').run(result)
3345
if not result.wasStrictlySuccessful():
3346
self.fail(output.getvalue())
3347
# We get our value back
3348
self.assertEquals('42', os.environ.get('MYVAR'))
3351
class TestIsolatedEnv(tests.TestCase):
3352
"""Test isolating tests from os.environ.
3354
Since we use tests that are already isolated from os.environ a bit of care
3355
should be taken when designing the tests to avoid bootstrap side-effects.
3356
The tests start an already clean os.environ which allow doing valid
3357
assertions about which variables are present or not and design tests around
3361
class ScratchMonkey(tests.TestCase):
3366
def test_basics(self):
3367
# Make sure we know the definition of BZR_HOME: not part of os.environ
3368
# for tests.TestCase.
3369
self.assertTrue('BZR_HOME' in tests.isolated_environ)
3370
self.assertEquals(None, tests.isolated_environ['BZR_HOME'])
3371
# Being part of isolated_environ, BZR_HOME should not appear here
3372
self.assertFalse('BZR_HOME' in os.environ)
3373
# Make sure we know the definition of LINES: part of os.environ for
3375
self.assertTrue('LINES' in tests.isolated_environ)
3376
self.assertEquals('25', tests.isolated_environ['LINES'])
3377
self.assertEquals('25', os.environ['LINES'])
3379
def test_injecting_unknown_variable(self):
3380
# BZR_HOME is known to be absent from os.environ
3381
test = self.ScratchMonkey('test_me')
3382
tests.override_os_environ(test, {'BZR_HOME': 'foo'})
3383
self.assertEquals('foo', os.environ['BZR_HOME'])
3384
tests.restore_os_environ(test)
3385
self.assertFalse('BZR_HOME' in os.environ)
3387
def test_injecting_known_variable(self):
3388
test = self.ScratchMonkey('test_me')
3389
# LINES is known to be present in os.environ
3390
tests.override_os_environ(test, {'LINES': '42'})
3391
self.assertEquals('42', os.environ['LINES'])
3392
tests.restore_os_environ(test)
3393
self.assertEquals('25', os.environ['LINES'])
3395
def test_deleting_variable(self):
3396
test = self.ScratchMonkey('test_me')
3397
# LINES is known to be present in os.environ
3398
tests.override_os_environ(test, {'LINES': None})
3399
self.assertTrue('LINES' not in os.environ)
3400
tests.restore_os_environ(test)
3401
self.assertEquals('25', os.environ['LINES'])
3404
class TestDocTestSuiteIsolation(tests.TestCase):
3405
"""Test that `tests.DocTestSuite` isolates doc tests from os.environ.
3407
Since tests.TestCase alreay provides an isolation from os.environ, we use
3408
the clean environment as a base for testing. To precisely capture the
3409
isolation provided by tests.DocTestSuite, we use doctest.DocTestSuite to
3412
We want to make sure `tests.DocTestSuite` respect `tests.isolated_environ`,
3413
not `os.environ` so each test overrides it to suit its needs.
3417
def get_doctest_suite_for_string(self, klass, string):
3418
class Finder(doctest.DocTestFinder):
3420
def find(*args, **kwargs):
3421
test = doctest.DocTestParser().get_doctest(
3422
string, {}, 'foo', 'foo.py', 0)
3425
suite = klass(test_finder=Finder())
3428
def run_doctest_suite_for_string(self, klass, string):
3429
suite = self.get_doctest_suite_for_string(klass, string)
3431
result = tests.TextTestResult(output, 0, 1)
3433
return result, output
3435
def assertDocTestStringSucceds(self, klass, string):
3436
result, output = self.run_doctest_suite_for_string(klass, string)
3437
if not result.wasStrictlySuccessful():
3438
self.fail(output.getvalue())
3440
def assertDocTestStringFails(self, klass, string):
3441
result, output = self.run_doctest_suite_for_string(klass, string)
3442
if result.wasStrictlySuccessful():
3443
self.fail(output.getvalue())
3445
def test_injected_variable(self):
3446
self.overrideAttr(tests, 'isolated_environ', {'LINES': '42'})
3449
>>> os.environ['LINES']
3452
# doctest.DocTestSuite fails as it sees '25'
3453
self.assertDocTestStringFails(doctest.DocTestSuite, test)
3454
# tests.DocTestSuite sees '42'
3455
self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
3457
def test_deleted_variable(self):
3458
self.overrideAttr(tests, 'isolated_environ', {'LINES': None})
3461
>>> os.environ.get('LINES')
3463
# doctest.DocTestSuite fails as it sees '25'
3464
self.assertDocTestStringFails(doctest.DocTestSuite, test)
3465
# tests.DocTestSuite sees None
3466
self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
3469
class TestSelftestExcludePatterns(tests.TestCase):
3472
super(TestSelftestExcludePatterns, self).setUp()
3473
self.overrideAttr(tests, 'test_suite', self.suite_factory)
3475
def suite_factory(self, keep_only=None, starting_with=None):
3476
"""A test suite factory with only a few tests."""
3477
class Test(tests.TestCase):
3479
# We don't need the full class path
3480
return self._testMethodName
3487
return TestUtil.TestSuite([Test("a"), Test("b"), Test("c")])
3489
def assertTestList(self, expected, *selftest_args):
3490
# We rely on setUp installing the right test suite factory so we can
3491
# test at the command level without loading the whole test suite
3492
out, err = self.run_bzr(('selftest', '--list') + selftest_args)
3493
actual = out.splitlines()
3494
self.assertEquals(expected, actual)
3496
def test_full_list(self):
3497
self.assertTestList(['a', 'b', 'c'])
3499
def test_single_exclude(self):
3500
self.assertTestList(['b', 'c'], '-x', 'a')
3502
def test_mutiple_excludes(self):
3503
self.assertTestList(['c'], '-x', 'a', '-x', 'b')
3506
class TestCounterHooks(tests.TestCase, SelfTestHelper):
3508
_test_needs_features = [features.subunit]
3511
super(TestCounterHooks, self).setUp()
3512
class Test(tests.TestCase):
3515
super(Test, self).setUp()
3516
self.hooks = hooks.Hooks()
3517
self.hooks.add_hook('myhook', 'Foo bar blah', (2,4))
3518
self.install_counter_hook(self.hooks, 'myhook')
3523
def run_hook_once(self):
3524
for hook in self.hooks['myhook']:
3527
self.test_class = Test
3529
def assertHookCalls(self, expected_calls, test_name):
3530
test = self.test_class(test_name)
3531
result = unittest.TestResult()
3533
self.assertTrue(hasattr(test, '_counters'))
3534
self.assertTrue(test._counters.has_key('myhook'))
3535
self.assertEquals(expected_calls, test._counters['myhook'])
3537
def test_no_hook(self):
3538
self.assertHookCalls(0, 'no_hook')
3540
def test_run_hook_once(self):
3541
tt = features.testtools
3542
if tt.module.__version__ < (0, 9, 8):
3543
raise tests.TestSkipped('testtools-0.9.8 required for addDetail')
3544
self.assertHookCalls(1, 'run_hook_once')