750
772
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
775
def _time_hello_world_encoding(self):
794
776
"""Profile two sleep calls
835
817
self.assertContainsRe(output,
836
818
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")
838
835
def test_known_failure(self):
839
836
"""A KnownFailure being raised should trigger several result actions."""
840
837
class InstrumentedTestResult(tests.ExtendedTestResult):
841
838
def stopTestRun(self): pass
842
def startTests(self): pass
843
def report_test_start(self, test): pass
839
def report_tests_starting(self): pass
844
840
def report_known_failure(self, test, err=None, details=None):
845
841
self._call = test, 'known failure'
846
842
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)
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")
1216
1229
def test_startTestRun(self):
1217
1230
"""run should call result.startTestRun()"""
1219
class LoggingDecorator(tests.ForwardingResult):
1232
class LoggingDecorator(ExtendedToOriginalDecorator):
1220
1233
def startTestRun(self):
1221
tests.ForwardingResult.startTestRun(self)
1234
ExtendedToOriginalDecorator.startTestRun(self)
1222
1235
calls.append('startTestRun')
1223
1236
test = unittest.FunctionTestCase(lambda:None)
1224
1237
stream = StringIO()
1655
1685
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)
1658
1824
# NB: Don't delete this; it's not actually from 0.11!
1659
1825
@deprecated_function(deprecated_in((0, 11, 0)))
1660
1826
def sample_deprecated_function():
1971
2134
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')
1974
2218
class TestRunBzr(tests.TestCase):
2960
3210
self.assertEquals('bzrlib.plugins', tpr.resolve_alias('bp'))
3213
class TestThreadLeakDetection(tests.TestCase):
3214
"""Ensure when tests leak threads we detect and report it"""
3216
class LeakRecordingResult(tests.ExtendedTestResult):
3218
tests.ExtendedTestResult.__init__(self, StringIO(), 0, 1)
3220
def _report_thread_leak(self, test, leaks, alive):
3221
self.leaks.append((test, leaks))
3223
def test_testcase_without_addCleanups(self):
3224
"""Check old TestCase instances don't break with leak detection"""
3225
class Test(unittest.TestCase):
3228
result = self.LeakRecordingResult()
3230
result.startTestRun()
3232
result.stopTestRun()
3233
self.assertEqual(result._tests_leaking_threads_count, 0)
3234
self.assertEqual(result.leaks, [])
3236
def test_thread_leak(self):
3237
"""Ensure a thread that outlives the running of a test is reported
3239
Uses a thread that blocks on an event, and is started by the inner
3240
test case. As the thread outlives the inner case's run, it should be
3241
detected as a leak, but the event is then set so that the thread can
3242
be safely joined in cleanup so it's not leaked for real.
3244
event = threading.Event()
3245
thread = threading.Thread(name="Leaker", target=event.wait)
3246
class Test(tests.TestCase):
3247
def test_leak(self):
3249
result = self.LeakRecordingResult()
3250
test = Test("test_leak")
3251
self.addCleanup(thread.join)
3252
self.addCleanup(event.set)
3253
result.startTestRun()
3255
result.stopTestRun()
3256
self.assertEqual(result._tests_leaking_threads_count, 1)
3257
self.assertEqual(result._first_thread_leaker_id, test.id())
3258
self.assertEqual(result.leaks, [(test, set([thread]))])
3259
self.assertContainsString(result.stream.getvalue(), "leaking threads")
3261
def test_multiple_leaks(self):
3262
"""Check multiple leaks are blamed on the test cases at fault
3264
Same concept as the previous test, but has one inner test method that
3265
leaks two threads, and one that doesn't leak at all.
3267
event = threading.Event()
3268
thread_a = threading.Thread(name="LeakerA", target=event.wait)
3269
thread_b = threading.Thread(name="LeakerB", target=event.wait)
3270
thread_c = threading.Thread(name="LeakerC", target=event.wait)
3271
class Test(tests.TestCase):
3272
def test_first_leak(self):
3274
def test_second_no_leak(self):
3276
def test_third_leak(self):
3279
result = self.LeakRecordingResult()
3280
first_test = Test("test_first_leak")
3281
third_test = Test("test_third_leak")
3282
self.addCleanup(thread_a.join)
3283
self.addCleanup(thread_b.join)
3284
self.addCleanup(thread_c.join)
3285
self.addCleanup(event.set)
3286
result.startTestRun()
3288
[first_test, Test("test_second_no_leak"), third_test]
3290
result.stopTestRun()
3291
self.assertEqual(result._tests_leaking_threads_count, 2)
3292
self.assertEqual(result._first_thread_leaker_id, first_test.id())
3293
self.assertEqual(result.leaks, [
3294
(first_test, set([thread_b])),
3295
(third_test, set([thread_a, thread_c]))])
3296
self.assertContainsString(result.stream.getvalue(), "leaking threads")
3299
class TestPostMortemDebugging(tests.TestCase):
3300
"""Check post mortem debugging works when tests fail or error"""
3302
class TracebackRecordingResult(tests.ExtendedTestResult):
3304
tests.ExtendedTestResult.__init__(self, StringIO(), 0, 1)
3305
self.postcode = None
3306
def _post_mortem(self, tb=None):
3307
"""Record the code object at the end of the current traceback"""
3308
tb = tb or sys.exc_info()[2]
3311
while next is not None:
3314
self.postcode = tb.tb_frame.f_code
3315
def report_error(self, test, err):
3317
def report_failure(self, test, err):
3320
def test_location_unittest_error(self):
3321
"""Needs right post mortem traceback with erroring unittest case"""
3322
class Test(unittest.TestCase):
3325
result = self.TracebackRecordingResult()
3327
self.assertEqual(result.postcode, Test.runTest.func_code)
3329
def test_location_unittest_failure(self):
3330
"""Needs right post mortem traceback with failing unittest case"""
3331
class Test(unittest.TestCase):
3333
raise self.failureException
3334
result = self.TracebackRecordingResult()
3336
self.assertEqual(result.postcode, Test.runTest.func_code)
3338
def test_location_bt_error(self):
3339
"""Needs right post mortem traceback with erroring bzrlib.tests case"""
3340
class Test(tests.TestCase):
3341
def test_error(self):
3343
result = self.TracebackRecordingResult()
3344
Test("test_error").run(result)
3345
self.assertEqual(result.postcode, Test.test_error.func_code)
3347
def test_location_bt_failure(self):
3348
"""Needs right post mortem traceback with failing bzrlib.tests case"""
3349
class Test(tests.TestCase):
3350
def test_failure(self):
3351
raise self.failureException
3352
result = self.TracebackRecordingResult()
3353
Test("test_failure").run(result)
3354
self.assertEqual(result.postcode, Test.test_failure.func_code)
3356
def test_env_var_triggers_post_mortem(self):
3357
"""Check pdb.post_mortem is called iff BZR_TEST_PDB is set"""
3359
result = tests.ExtendedTestResult(StringIO(), 0, 1)
3360
post_mortem_calls = []
3361
self.overrideAttr(pdb, "post_mortem", post_mortem_calls.append)
3362
self.overrideEnv('BZR_TEST_PDB', None)
3363
result._post_mortem(1)
3364
self.overrideEnv('BZR_TEST_PDB', 'on')
3365
result._post_mortem(2)
3366
self.assertEqual([2], post_mortem_calls)
2963
3369
class TestRunSuite(tests.TestCase):
2965
3371
def test_runner_class(self):
2976
3382
self.verbosity)
2977
3383
tests.run_suite(suite, runner_class=MyRunner, stream=StringIO())
2978
3384
self.assertLength(1, calls)
3387
class TestEnvironHandling(tests.TestCase):
3389
def test_overrideEnv_None_called_twice_doesnt_leak(self):
3390
self.assertFalse('MYVAR' in os.environ)
3391
self.overrideEnv('MYVAR', '42')
3392
# We use an embedded test to make sure we fix the _captureVar bug
3393
class Test(tests.TestCase):
3395
# The first call save the 42 value
3396
self.overrideEnv('MYVAR', None)
3397
self.assertEquals(None, os.environ.get('MYVAR'))
3398
# Make sure we can call it twice
3399
self.overrideEnv('MYVAR', None)
3400
self.assertEquals(None, os.environ.get('MYVAR'))
3402
result = tests.TextTestResult(output, 0, 1)
3403
Test('test_me').run(result)
3404
if not result.wasStrictlySuccessful():
3405
self.fail(output.getvalue())
3406
# We get our value back
3407
self.assertEquals('42', os.environ.get('MYVAR'))
3410
class TestIsolatedEnv(tests.TestCase):
3411
"""Test isolating tests from os.environ.
3413
Since we use tests that are already isolated from os.environ a bit of care
3414
should be taken when designing the tests to avoid bootstrap side-effects.
3415
The tests start an already clean os.environ which allow doing valid
3416
assertions about which variables are present or not and design tests around
3420
class ScratchMonkey(tests.TestCase):
3425
def test_basics(self):
3426
# Make sure we know the definition of BZR_HOME: not part of os.environ
3427
# for tests.TestCase.
3428
self.assertTrue('BZR_HOME' in tests.isolated_environ)
3429
self.assertEquals(None, tests.isolated_environ['BZR_HOME'])
3430
# Being part of isolated_environ, BZR_HOME should not appear here
3431
self.assertFalse('BZR_HOME' in os.environ)
3432
# Make sure we know the definition of LINES: part of os.environ for
3434
self.assertTrue('LINES' in tests.isolated_environ)
3435
self.assertEquals('25', tests.isolated_environ['LINES'])
3436
self.assertEquals('25', os.environ['LINES'])
3438
def test_injecting_unknown_variable(self):
3439
# BZR_HOME is known to be absent from os.environ
3440
test = self.ScratchMonkey('test_me')
3441
tests.override_os_environ(test, {'BZR_HOME': 'foo'})
3442
self.assertEquals('foo', os.environ['BZR_HOME'])
3443
tests.restore_os_environ(test)
3444
self.assertFalse('BZR_HOME' in os.environ)
3446
def test_injecting_known_variable(self):
3447
test = self.ScratchMonkey('test_me')
3448
# LINES is known to be present in os.environ
3449
tests.override_os_environ(test, {'LINES': '42'})
3450
self.assertEquals('42', os.environ['LINES'])
3451
tests.restore_os_environ(test)
3452
self.assertEquals('25', os.environ['LINES'])
3454
def test_deleting_variable(self):
3455
test = self.ScratchMonkey('test_me')
3456
# LINES is known to be present in os.environ
3457
tests.override_os_environ(test, {'LINES': None})
3458
self.assertTrue('LINES' not in os.environ)
3459
tests.restore_os_environ(test)
3460
self.assertEquals('25', os.environ['LINES'])
3463
class TestDocTestSuiteIsolation(tests.TestCase):
3464
"""Test that `tests.DocTestSuite` isolates doc tests from os.environ.
3466
Since tests.TestCase alreay provides an isolation from os.environ, we use
3467
the clean environment as a base for testing. To precisely capture the
3468
isolation provided by tests.DocTestSuite, we use doctest.DocTestSuite to
3471
We want to make sure `tests.DocTestSuite` respect `tests.isolated_environ`,
3472
not `os.environ` so each test overrides it to suit its needs.
3476
def get_doctest_suite_for_string(self, klass, string):
3477
class Finder(doctest.DocTestFinder):
3479
def find(*args, **kwargs):
3480
test = doctest.DocTestParser().get_doctest(
3481
string, {}, 'foo', 'foo.py', 0)
3484
suite = klass(test_finder=Finder())
3487
def run_doctest_suite_for_string(self, klass, string):
3488
suite = self.get_doctest_suite_for_string(klass, string)
3490
result = tests.TextTestResult(output, 0, 1)
3492
return result, output
3494
def assertDocTestStringSucceds(self, klass, string):
3495
result, output = self.run_doctest_suite_for_string(klass, string)
3496
if not result.wasStrictlySuccessful():
3497
self.fail(output.getvalue())
3499
def assertDocTestStringFails(self, klass, string):
3500
result, output = self.run_doctest_suite_for_string(klass, string)
3501
if result.wasStrictlySuccessful():
3502
self.fail(output.getvalue())
3504
def test_injected_variable(self):
3505
self.overrideAttr(tests, 'isolated_environ', {'LINES': '42'})
3508
>>> os.environ['LINES']
3511
# doctest.DocTestSuite fails as it sees '25'
3512
self.assertDocTestStringFails(doctest.DocTestSuite, test)
3513
# tests.DocTestSuite sees '42'
3514
self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
3516
def test_deleted_variable(self):
3517
self.overrideAttr(tests, 'isolated_environ', {'LINES': None})
3520
>>> os.environ.get('LINES')
3522
# doctest.DocTestSuite fails as it sees '25'
3523
self.assertDocTestStringFails(doctest.DocTestSuite, test)
3524
# tests.DocTestSuite sees None
3525
self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
3528
class TestSelftestExcludePatterns(tests.TestCase):
3531
super(TestSelftestExcludePatterns, self).setUp()
3532
self.overrideAttr(tests, 'test_suite', self.suite_factory)
3534
def suite_factory(self, keep_only=None, starting_with=None):
3535
"""A test suite factory with only a few tests."""
3536
class Test(tests.TestCase):
3538
# We don't need the full class path
3539
return self._testMethodName
3546
return TestUtil.TestSuite([Test("a"), Test("b"), Test("c")])
3548
def assertTestList(self, expected, *selftest_args):
3549
# We rely on setUp installing the right test suite factory so we can
3550
# test at the command level without loading the whole test suite
3551
out, err = self.run_bzr(('selftest', '--list') + selftest_args)
3552
actual = out.splitlines()
3553
self.assertEquals(expected, actual)
3555
def test_full_list(self):
3556
self.assertTestList(['a', 'b', 'c'])
3558
def test_single_exclude(self):
3559
self.assertTestList(['b', 'c'], '-x', 'a')
3561
def test_mutiple_excludes(self):
3562
self.assertTestList(['c'], '-x', 'a', '-x', 'b')
3565
class TestCounterHooks(tests.TestCase, SelfTestHelper):
3567
_test_needs_features = [features.subunit]
3570
super(TestCounterHooks, self).setUp()
3571
class Test(tests.TestCase):
3574
super(Test, self).setUp()
3575
self.hooks = hooks.Hooks()
3576
self.hooks.add_hook('myhook', 'Foo bar blah', (2,4))
3577
self.install_counter_hook(self.hooks, 'myhook')
3582
def run_hook_once(self):
3583
for hook in self.hooks['myhook']:
3585
self.test_class = Test
3587
def assertHookCalls(self, expected_calls, test_name):
3588
test = self.test_class(test_name)
3589
result = unittest.TestResult()
3591
self.assertTrue(hasattr(test, '_counters'))
3592
self.assertTrue(test._counters.has_key('myhook'))
3593
self.assertEquals(expected_calls, test._counters['myhook'])
3595
def test_no_hook(self):
3596
self.assertHookCalls(0, 'no_hook')
3598
def test_run_hook_once(self):
3599
self.assertHookCalls(1, 'run_hook_once')