1674
1652
test.run(unittest.TestResult())
1675
1653
self.assertEqual('original', obj.test_attr)
1677
def test_recordCalls(self):
1678
from bzrlib.tests import test_selftest
1679
calls = self.recordCalls(
1680
test_selftest, '_add_numbers')
1681
self.assertEqual(test_selftest._add_numbers(2, 10),
1683
self.assertEquals(calls, [((2, 10), {})])
1686
def _add_numbers(a, b):
1690
class _MissingFeature(features.Feature):
1693
missing_feature = _MissingFeature()
1696
def _get_test(name):
1697
"""Get an instance of a specific example test.
1699
We protect this in a function so that they don't auto-run in the test
1703
class ExampleTests(tests.TestCase):
1705
def test_fail(self):
1706
mutter('this was a failing test')
1707
self.fail('this test will fail')
1709
def test_error(self):
1710
mutter('this test errored')
1711
raise RuntimeError('gotcha')
1713
def test_missing_feature(self):
1714
mutter('missing the feature')
1715
self.requireFeature(missing_feature)
1717
def test_skip(self):
1718
mutter('this test will be skipped')
1719
raise tests.TestSkipped('reason')
1721
def test_success(self):
1722
mutter('this test succeeds')
1724
def test_xfail(self):
1725
mutter('test with expected failure')
1726
self.knownFailure('this_fails')
1728
def test_unexpected_success(self):
1729
mutter('test with unexpected success')
1730
self.expectFailure('should_fail', lambda: None)
1732
return ExampleTests(name)
1735
class TestTestCaseLogDetails(tests.TestCase):
1737
def _run_test(self, test_name):
1738
test = _get_test(test_name)
1739
result = testtools.TestResult()
1743
def test_fail_has_log(self):
1744
result = self._run_test('test_fail')
1745
self.assertEqual(1, len(result.failures))
1746
result_content = result.failures[0][1]
1747
if testtools_version < (0, 9, 12):
1748
self.assertContainsRe(result_content, 'Text attachment: log')
1749
self.assertContainsRe(result_content, 'this was a failing test')
1751
def test_error_has_log(self):
1752
result = self._run_test('test_error')
1753
self.assertEqual(1, len(result.errors))
1754
result_content = result.errors[0][1]
1755
if testtools_version < (0, 9, 12):
1756
self.assertContainsRe(result_content, 'Text attachment: log')
1757
self.assertContainsRe(result_content, 'this test errored')
1759
def test_skip_has_no_log(self):
1760
result = self._run_test('test_skip')
1761
self.assertEqual(['reason'], result.skip_reasons.keys())
1762
skips = result.skip_reasons['reason']
1763
self.assertEqual(1, len(skips))
1765
self.assertFalse('log' in test.getDetails())
1767
def test_missing_feature_has_no_log(self):
1768
# testtools doesn't know about addNotSupported, so it just gets
1769
# considered as a skip
1770
result = self._run_test('test_missing_feature')
1771
self.assertEqual([missing_feature], result.skip_reasons.keys())
1772
skips = result.skip_reasons[missing_feature]
1773
self.assertEqual(1, len(skips))
1775
self.assertFalse('log' in test.getDetails())
1777
def test_xfail_has_no_log(self):
1778
result = self._run_test('test_xfail')
1779
self.assertEqual(1, len(result.expectedFailures))
1780
result_content = result.expectedFailures[0][1]
1781
self.assertNotContainsRe(result_content, 'Text attachment: log')
1782
self.assertNotContainsRe(result_content, 'test with expected failure')
1784
def test_unexpected_success_has_log(self):
1785
result = self._run_test('test_unexpected_success')
1786
self.assertEqual(1, len(result.unexpectedSuccesses))
1787
# Inconsistency, unexpectedSuccesses is a list of tests,
1788
# expectedFailures is a list of reasons?
1789
test = result.unexpectedSuccesses[0]
1790
details = test.getDetails()
1791
self.assertTrue('log' in details)
1794
class TestTestCloning(tests.TestCase):
1795
"""Tests that test cloning of TestCases (as used by multiply_tests)."""
1797
def test_cloned_testcase_does_not_share_details(self):
1798
"""A TestCase cloned with clone_test does not share mutable attributes
1799
such as details or cleanups.
1801
class Test(tests.TestCase):
1803
self.addDetail('foo', Content('text/plain', lambda: 'foo'))
1804
orig_test = Test('test_foo')
1805
cloned_test = tests.clone_test(orig_test, orig_test.id() + '(cloned)')
1806
orig_test.run(unittest.TestResult())
1807
self.assertEqual('foo', orig_test.getDetails()['foo'].iter_bytes())
1808
self.assertEqual(None, cloned_test.getDetails().get('foo'))
1810
def test_double_apply_scenario_preserves_first_scenario(self):
1811
"""Applying two levels of scenarios to a test preserves the attributes
1812
added by both scenarios.
1814
class Test(tests.TestCase):
1817
test = Test('test_foo')
1818
scenarios_x = [('x=1', {'x': 1}), ('x=2', {'x': 2})]
1819
scenarios_y = [('y=1', {'y': 1}), ('y=2', {'y': 2})]
1820
suite = tests.multiply_tests(test, scenarios_x, unittest.TestSuite())
1821
suite = tests.multiply_tests(suite, scenarios_y, unittest.TestSuite())
1822
all_tests = list(tests.iter_suite_tests(suite))
1823
self.assertLength(4, all_tests)
1824
all_xys = sorted((t.x, t.y) for t in all_tests)
1825
self.assertEqual([(1, 1), (1, 2), (2, 1), (2, 2)], all_xys)
1828
1656
# NB: Don't delete this; it's not actually from 0.11!
1829
1657
@deprecated_function(deprecated_in((0, 11, 0)))
2138
1969
load_list='missing file name', list_only=True)
2141
class TestSubunitLogDetails(tests.TestCase, SelfTestHelper):
2143
_test_needs_features = [features.subunit]
2145
def run_subunit_stream(self, test_name):
2146
from subunit import ProtocolTestCase
2148
return TestUtil.TestSuite([_get_test(test_name)])
2149
stream = self.run_selftest(runner_class=tests.SubUnitBzrRunner,
2150
test_suite_factory=factory)
2151
test = ProtocolTestCase(stream)
2152
result = testtools.TestResult()
2154
content = stream.getvalue()
2155
return content, result
2157
def test_fail_has_log(self):
2158
content, result = self.run_subunit_stream('test_fail')
2159
self.assertEqual(1, len(result.failures))
2160
self.assertContainsRe(content, '(?m)^log$')
2161
self.assertContainsRe(content, 'this test will fail')
2163
def test_error_has_log(self):
2164
content, result = self.run_subunit_stream('test_error')
2165
self.assertContainsRe(content, '(?m)^log$')
2166
self.assertContainsRe(content, 'this test errored')
2168
def test_skip_has_no_log(self):
2169
content, result = self.run_subunit_stream('test_skip')
2170
self.assertNotContainsRe(content, '(?m)^log$')
2171
self.assertNotContainsRe(content, 'this test will be skipped')
2172
self.assertEqual(['reason'], result.skip_reasons.keys())
2173
skips = result.skip_reasons['reason']
2174
self.assertEqual(1, len(skips))
2176
# RemotedTestCase doesn't preserve the "details"
2177
## self.assertFalse('log' in test.getDetails())
2179
def test_missing_feature_has_no_log(self):
2180
content, result = self.run_subunit_stream('test_missing_feature')
2181
self.assertNotContainsRe(content, '(?m)^log$')
2182
self.assertNotContainsRe(content, 'missing the feature')
2183
self.assertEqual(['_MissingFeature\n'], result.skip_reasons.keys())
2184
skips = result.skip_reasons['_MissingFeature\n']
2185
self.assertEqual(1, len(skips))
2187
# RemotedTestCase doesn't preserve the "details"
2188
## self.assertFalse('log' in test.getDetails())
2190
def test_xfail_has_no_log(self):
2191
content, result = self.run_subunit_stream('test_xfail')
2192
self.assertNotContainsRe(content, '(?m)^log$')
2193
self.assertNotContainsRe(content, 'test with expected failure')
2194
self.assertEqual(1, len(result.expectedFailures))
2195
result_content = result.expectedFailures[0][1]
2196
self.assertNotContainsRe(result_content, 'Text attachment: log')
2197
self.assertNotContainsRe(result_content, 'test with expected failure')
2199
def test_unexpected_success_has_log(self):
2200
content, result = self.run_subunit_stream('test_unexpected_success')
2201
self.assertContainsRe(content, '(?m)^log$')
2202
self.assertContainsRe(content, 'test with unexpected success')
2203
# GZ 2011-05-18: Old versions of subunit treat unexpected success as a
2204
# success, if a min version check is added remove this
2205
from subunit import TestProtocolClient as _Client
2206
if _Client.addUnexpectedSuccess.im_func is _Client.addSuccess.im_func:
2207
self.expectFailure('subunit treats "unexpectedSuccess"'
2208
' as a plain success',
2209
self.assertEqual, 1, len(result.unexpectedSuccesses))
2210
self.assertEqual(1, len(result.unexpectedSuccesses))
2211
test = result.unexpectedSuccesses[0]
2212
# RemotedTestCase doesn't preserve the "details"
2213
## self.assertTrue('log' in test.getDetails())
2215
def test_success_has_no_log(self):
2216
content, result = self.run_subunit_stream('test_success')
2217
self.assertEqual(1, result.testsRun)
2218
self.assertNotContainsRe(content, '(?m)^log$')
2219
self.assertNotContainsRe(content, 'this test succeeds')
2222
1972
class TestRunBzr(tests.TestCase):
2611
2360
self.assertEqual('bzr: interrupted\n', result[1])
2363
class TestFeature(tests.TestCase):
2365
def test_caching(self):
2366
"""Feature._probe is called by the feature at most once."""
2367
class InstrumentedFeature(tests.Feature):
2369
super(InstrumentedFeature, self).__init__()
2372
self.calls.append('_probe')
2374
feature = InstrumentedFeature()
2376
self.assertEqual(['_probe'], feature.calls)
2378
self.assertEqual(['_probe'], feature.calls)
2380
def test_named_str(self):
2381
"""Feature.__str__ should thunk to feature_name()."""
2382
class NamedFeature(tests.Feature):
2383
def feature_name(self):
2385
feature = NamedFeature()
2386
self.assertEqual('symlinks', str(feature))
2388
def test_default_str(self):
2389
"""Feature.__str__ should default to __class__.__name__."""
2390
class NamedFeature(tests.Feature):
2392
feature = NamedFeature()
2393
self.assertEqual('NamedFeature', str(feature))
2396
class TestUnavailableFeature(tests.TestCase):
2398
def test_access_feature(self):
2399
feature = tests.Feature()
2400
exception = tests.UnavailableFeature(feature)
2401
self.assertIs(feature, exception.args[0])
2404
simple_thunk_feature = tests._CompatabilityThunkFeature(
2405
deprecated_in((2, 1, 0)),
2406
'bzrlib.tests.test_selftest',
2407
'simple_thunk_feature','UnicodeFilename',
2408
replacement_module='bzrlib.tests'
2411
class Test_CompatibilityFeature(tests.TestCase):
2413
def test_does_thunk(self):
2414
res = self.callDeprecated(
2415
['bzrlib.tests.test_selftest.simple_thunk_feature was deprecated'
2416
' in version 2.1.0. Use bzrlib.tests.UnicodeFilename instead.'],
2417
simple_thunk_feature.available)
2418
self.assertEqual(tests.UnicodeFilename.available(), res)
2421
class TestModuleAvailableFeature(tests.TestCase):
2423
def test_available_module(self):
2424
feature = tests.ModuleAvailableFeature('bzrlib.tests')
2425
self.assertEqual('bzrlib.tests', feature.module_name)
2426
self.assertEqual('bzrlib.tests', str(feature))
2427
self.assertTrue(feature.available())
2428
self.assertIs(tests, feature.module)
2430
def test_unavailable_module(self):
2431
feature = tests.ModuleAvailableFeature('bzrlib.no_such_module_exists')
2432
self.assertEqual('bzrlib.no_such_module_exists', str(feature))
2433
self.assertFalse(feature.available())
2434
self.assertIs(None, feature.module)
2614
2437
class TestSelftestFiltering(tests.TestCase):
2616
2439
def setUp(self):
3141
2963
self.assertEquals('bzrlib.plugins', tpr.resolve_alias('bp'))
3144
class TestThreadLeakDetection(tests.TestCase):
3145
"""Ensure when tests leak threads we detect and report it"""
3147
class LeakRecordingResult(tests.ExtendedTestResult):
3149
tests.ExtendedTestResult.__init__(self, StringIO(), 0, 1)
3151
def _report_thread_leak(self, test, leaks, alive):
3152
self.leaks.append((test, leaks))
3154
def test_testcase_without_addCleanups(self):
3155
"""Check old TestCase instances don't break with leak detection"""
3156
class Test(unittest.TestCase):
3159
result = self.LeakRecordingResult()
3161
result.startTestRun()
3163
result.stopTestRun()
3164
self.assertEqual(result._tests_leaking_threads_count, 0)
3165
self.assertEqual(result.leaks, [])
3167
def test_thread_leak(self):
3168
"""Ensure a thread that outlives the running of a test is reported
3170
Uses a thread that blocks on an event, and is started by the inner
3171
test case. As the thread outlives the inner case's run, it should be
3172
detected as a leak, but the event is then set so that the thread can
3173
be safely joined in cleanup so it's not leaked for real.
3175
event = threading.Event()
3176
thread = threading.Thread(name="Leaker", target=event.wait)
3177
class Test(tests.TestCase):
3178
def test_leak(self):
3180
result = self.LeakRecordingResult()
3181
test = Test("test_leak")
3182
self.addCleanup(thread.join)
3183
self.addCleanup(event.set)
3184
result.startTestRun()
3186
result.stopTestRun()
3187
self.assertEqual(result._tests_leaking_threads_count, 1)
3188
self.assertEqual(result._first_thread_leaker_id, test.id())
3189
self.assertEqual(result.leaks, [(test, set([thread]))])
3190
self.assertContainsString(result.stream.getvalue(), "leaking threads")
3192
def test_multiple_leaks(self):
3193
"""Check multiple leaks are blamed on the test cases at fault
3195
Same concept as the previous test, but has one inner test method that
3196
leaks two threads, and one that doesn't leak at all.
3198
event = threading.Event()
3199
thread_a = threading.Thread(name="LeakerA", target=event.wait)
3200
thread_b = threading.Thread(name="LeakerB", target=event.wait)
3201
thread_c = threading.Thread(name="LeakerC", target=event.wait)
3202
class Test(tests.TestCase):
3203
def test_first_leak(self):
3205
def test_second_no_leak(self):
3207
def test_third_leak(self):
3210
result = self.LeakRecordingResult()
3211
first_test = Test("test_first_leak")
3212
third_test = Test("test_third_leak")
3213
self.addCleanup(thread_a.join)
3214
self.addCleanup(thread_b.join)
3215
self.addCleanup(thread_c.join)
3216
self.addCleanup(event.set)
3217
result.startTestRun()
3219
[first_test, Test("test_second_no_leak"), third_test]
3221
result.stopTestRun()
3222
self.assertEqual(result._tests_leaking_threads_count, 2)
3223
self.assertEqual(result._first_thread_leaker_id, first_test.id())
3224
self.assertEqual(result.leaks, [
3225
(first_test, set([thread_b])),
3226
(third_test, set([thread_a, thread_c]))])
3227
self.assertContainsString(result.stream.getvalue(), "leaking threads")
3230
class TestPostMortemDebugging(tests.TestCase):
3231
"""Check post mortem debugging works when tests fail or error"""
3233
class TracebackRecordingResult(tests.ExtendedTestResult):
3235
tests.ExtendedTestResult.__init__(self, StringIO(), 0, 1)
3236
self.postcode = None
3237
def _post_mortem(self, tb=None):
3238
"""Record the code object at the end of the current traceback"""
3239
tb = tb or sys.exc_info()[2]
3242
while next is not None:
3245
self.postcode = tb.tb_frame.f_code
3246
def report_error(self, test, err):
3248
def report_failure(self, test, err):
3251
def test_location_unittest_error(self):
3252
"""Needs right post mortem traceback with erroring unittest case"""
3253
class Test(unittest.TestCase):
3256
result = self.TracebackRecordingResult()
3258
self.assertEqual(result.postcode, Test.runTest.func_code)
3260
def test_location_unittest_failure(self):
3261
"""Needs right post mortem traceback with failing unittest case"""
3262
class Test(unittest.TestCase):
3264
raise self.failureException
3265
result = self.TracebackRecordingResult()
3267
self.assertEqual(result.postcode, Test.runTest.func_code)
3269
def test_location_bt_error(self):
3270
"""Needs right post mortem traceback with erroring bzrlib.tests case"""
3271
class Test(tests.TestCase):
3272
def test_error(self):
3274
result = self.TracebackRecordingResult()
3275
Test("test_error").run(result)
3276
self.assertEqual(result.postcode, Test.test_error.func_code)
3278
def test_location_bt_failure(self):
3279
"""Needs right post mortem traceback with failing bzrlib.tests case"""
3280
class Test(tests.TestCase):
3281
def test_failure(self):
3282
raise self.failureException
3283
result = self.TracebackRecordingResult()
3284
Test("test_failure").run(result)
3285
self.assertEqual(result.postcode, Test.test_failure.func_code)
3287
def test_env_var_triggers_post_mortem(self):
3288
"""Check pdb.post_mortem is called iff BZR_TEST_PDB is set"""
3290
result = tests.ExtendedTestResult(StringIO(), 0, 1)
3291
post_mortem_calls = []
3292
self.overrideAttr(pdb, "post_mortem", post_mortem_calls.append)
3293
self.overrideEnv('BZR_TEST_PDB', None)
3294
result._post_mortem(1)
3295
self.overrideEnv('BZR_TEST_PDB', 'on')
3296
result._post_mortem(2)
3297
self.assertEqual([2], post_mortem_calls)
3300
2966
class TestRunSuite(tests.TestCase):
3302
2968
def test_runner_class(self):
3313
2979
self.verbosity)
3314
2980
tests.run_suite(suite, runner_class=MyRunner, stream=StringIO())
3315
2981
self.assertLength(1, calls)
3318
class TestUncollectedWarnings(tests.TestCase):
3319
"""Check a test case still alive after being run emits a warning"""
3321
class Test(tests.TestCase):
3322
def test_pass(self):
3324
def test_self_ref(self):
3325
self.also_self = self.test_self_ref
3326
def test_skip(self):
3327
self.skip("Don't need")
3329
def _get_suite(self):
3330
return TestUtil.TestSuite([
3331
self.Test("test_pass"),
3332
self.Test("test_self_ref"),
3333
self.Test("test_skip"),
3336
def _inject_stream_into_subunit(self, stream):
3337
"""To be overridden by subclasses that run tests out of process"""
3339
def _run_selftest_with_suite(self, **kwargs):
3341
self._inject_stream_into_subunit(sio)
3342
old_flags = tests.selftest_debug_flags
3343
tests.selftest_debug_flags = old_flags.union(["uncollected_cases"])
3344
gc_on = gc.isenabled()
3348
tests.selftest(test_suite_factory=self._get_suite, stream=sio,
3349
stop_on_failure=False, **kwargs)
3353
tests.selftest_debug_flags = old_flags
3354
output = sio.getvalue()
3355
self.assertNotContainsRe(output, "Uncollected test case.*test_pass")
3356
self.assertContainsRe(output, "Uncollected test case.*test_self_ref")
3359
def test_testsuite(self):
3360
self._run_selftest_with_suite()
3362
def test_pattern(self):
3363
out = self._run_selftest_with_suite(pattern="test_(?:pass|self_ref)$")
3364
self.assertNotContainsRe(out, "test_skip")
3366
def test_exclude_pattern(self):
3367
out = self._run_selftest_with_suite(exclude_pattern="test_skip$")
3368
self.assertNotContainsRe(out, "test_skip")
3370
def test_random_seed(self):
3371
self._run_selftest_with_suite(random_seed="now")
3373
def test_matching_tests_first(self):
3374
self._run_selftest_with_suite(matching_tests_first=True,
3375
pattern="test_self_ref$")
3377
def test_starting_with_and_exclude(self):
3378
out = self._run_selftest_with_suite(starting_with=["bt."],
3379
exclude_pattern="test_skip$")
3380
self.assertNotContainsRe(out, "test_skip")
3382
def test_additonal_decorator(self):
3383
out = self._run_selftest_with_suite(
3384
suite_decorators=[tests.TestDecorator])
3387
class TestUncollectedWarningsSubunit(TestUncollectedWarnings):
3388
"""Check warnings from tests staying alive are emitted with subunit"""
3390
_test_needs_features = [features.subunit]
3392
def _run_selftest_with_suite(self, **kwargs):
3393
return TestUncollectedWarnings._run_selftest_with_suite(self,
3394
runner_class=tests.SubUnitBzrRunner, **kwargs)
3397
class TestUncollectedWarningsForking(TestUncollectedWarnings):
3398
"""Check warnings from tests staying alive are emitted when forking"""
3400
_test_needs_features = [features.subunit]
3402
def _inject_stream_into_subunit(self, stream):
3403
"""Monkey-patch subunit so the extra output goes to stream not stdout
3405
Some APIs need rewriting so this kind of bogus hackery can be replaced
3406
by passing the stream param from run_tests down into ProtocolTestCase.
3408
from subunit import ProtocolTestCase
3409
_original_init = ProtocolTestCase.__init__
3410
def _init_with_passthrough(self, *args, **kwargs):
3411
_original_init(self, *args, **kwargs)
3412
self._passthrough = stream
3413
self.overrideAttr(ProtocolTestCase, "__init__", _init_with_passthrough)
3415
def _run_selftest_with_suite(self, **kwargs):
3416
# GZ 2011-05-26: Add a PosixSystem feature so this check can go away
3417
if getattr(os, "fork", None) is None:
3418
raise tests.TestNotApplicable("Platform doesn't support forking")
3419
# Make sure the fork code is actually invoked by claiming two cores
3420
self.overrideAttr(osutils, "local_concurrency", lambda: 2)
3421
kwargs.setdefault("suite_decorators", []).append(tests.fork_decorator)
3422
return TestUncollectedWarnings._run_selftest_with_suite(self, **kwargs)
3425
class TestEnvironHandling(tests.TestCase):
3427
def test_overrideEnv_None_called_twice_doesnt_leak(self):
3428
self.assertFalse('MYVAR' in os.environ)
3429
self.overrideEnv('MYVAR', '42')
3430
# We use an embedded test to make sure we fix the _captureVar bug
3431
class Test(tests.TestCase):
3433
# The first call save the 42 value
3434
self.overrideEnv('MYVAR', None)
3435
self.assertEquals(None, os.environ.get('MYVAR'))
3436
# Make sure we can call it twice
3437
self.overrideEnv('MYVAR', None)
3438
self.assertEquals(None, os.environ.get('MYVAR'))
3440
result = tests.TextTestResult(output, 0, 1)
3441
Test('test_me').run(result)
3442
if not result.wasStrictlySuccessful():
3443
self.fail(output.getvalue())
3444
# We get our value back
3445
self.assertEquals('42', os.environ.get('MYVAR'))
3448
class TestIsolatedEnv(tests.TestCase):
3449
"""Test isolating tests from os.environ.
3451
Since we use tests that are already isolated from os.environ a bit of care
3452
should be taken when designing the tests to avoid bootstrap side-effects.
3453
The tests start an already clean os.environ which allow doing valid
3454
assertions about which variables are present or not and design tests around
3458
class ScratchMonkey(tests.TestCase):
3463
def test_basics(self):
3464
# Make sure we know the definition of BZR_HOME: not part of os.environ
3465
# for tests.TestCase.
3466
self.assertTrue('BZR_HOME' in tests.isolated_environ)
3467
self.assertEquals(None, tests.isolated_environ['BZR_HOME'])
3468
# Being part of isolated_environ, BZR_HOME should not appear here
3469
self.assertFalse('BZR_HOME' in os.environ)
3470
# Make sure we know the definition of LINES: part of os.environ for
3472
self.assertTrue('LINES' in tests.isolated_environ)
3473
self.assertEquals('25', tests.isolated_environ['LINES'])
3474
self.assertEquals('25', os.environ['LINES'])
3476
def test_injecting_unknown_variable(self):
3477
# BZR_HOME is known to be absent from os.environ
3478
test = self.ScratchMonkey('test_me')
3479
tests.override_os_environ(test, {'BZR_HOME': 'foo'})
3480
self.assertEquals('foo', os.environ['BZR_HOME'])
3481
tests.restore_os_environ(test)
3482
self.assertFalse('BZR_HOME' in os.environ)
3484
def test_injecting_known_variable(self):
3485
test = self.ScratchMonkey('test_me')
3486
# LINES is known to be present in os.environ
3487
tests.override_os_environ(test, {'LINES': '42'})
3488
self.assertEquals('42', os.environ['LINES'])
3489
tests.restore_os_environ(test)
3490
self.assertEquals('25', os.environ['LINES'])
3492
def test_deleting_variable(self):
3493
test = self.ScratchMonkey('test_me')
3494
# LINES is known to be present in os.environ
3495
tests.override_os_environ(test, {'LINES': None})
3496
self.assertTrue('LINES' not in os.environ)
3497
tests.restore_os_environ(test)
3498
self.assertEquals('25', os.environ['LINES'])
3501
class TestDocTestSuiteIsolation(tests.TestCase):
3502
"""Test that `tests.DocTestSuite` isolates doc tests from os.environ.
3504
Since tests.TestCase alreay provides an isolation from os.environ, we use
3505
the clean environment as a base for testing. To precisely capture the
3506
isolation provided by tests.DocTestSuite, we use doctest.DocTestSuite to
3509
We want to make sure `tests.DocTestSuite` respect `tests.isolated_environ`,
3510
not `os.environ` so each test overrides it to suit its needs.
3514
def get_doctest_suite_for_string(self, klass, string):
3515
class Finder(doctest.DocTestFinder):
3517
def find(*args, **kwargs):
3518
test = doctest.DocTestParser().get_doctest(
3519
string, {}, 'foo', 'foo.py', 0)
3522
suite = klass(test_finder=Finder())
3525
def run_doctest_suite_for_string(self, klass, string):
3526
suite = self.get_doctest_suite_for_string(klass, string)
3528
result = tests.TextTestResult(output, 0, 1)
3530
return result, output
3532
def assertDocTestStringSucceds(self, klass, string):
3533
result, output = self.run_doctest_suite_for_string(klass, string)
3534
if not result.wasStrictlySuccessful():
3535
self.fail(output.getvalue())
3537
def assertDocTestStringFails(self, klass, string):
3538
result, output = self.run_doctest_suite_for_string(klass, string)
3539
if result.wasStrictlySuccessful():
3540
self.fail(output.getvalue())
3542
def test_injected_variable(self):
3543
self.overrideAttr(tests, 'isolated_environ', {'LINES': '42'})
3546
>>> os.environ['LINES']
3549
# doctest.DocTestSuite fails as it sees '25'
3550
self.assertDocTestStringFails(doctest.DocTestSuite, test)
3551
# tests.DocTestSuite sees '42'
3552
self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
3554
def test_deleted_variable(self):
3555
self.overrideAttr(tests, 'isolated_environ', {'LINES': None})
3558
>>> os.environ.get('LINES')
3560
# doctest.DocTestSuite fails as it sees '25'
3561
self.assertDocTestStringFails(doctest.DocTestSuite, test)
3562
# tests.DocTestSuite sees None
3563
self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
3566
class TestSelftestExcludePatterns(tests.TestCase):
3569
super(TestSelftestExcludePatterns, self).setUp()
3570
self.overrideAttr(tests, 'test_suite', self.suite_factory)
3572
def suite_factory(self, keep_only=None, starting_with=None):
3573
"""A test suite factory with only a few tests."""
3574
class Test(tests.TestCase):
3576
# We don't need the full class path
3577
return self._testMethodName
3584
return TestUtil.TestSuite([Test("a"), Test("b"), Test("c")])
3586
def assertTestList(self, expected, *selftest_args):
3587
# We rely on setUp installing the right test suite factory so we can
3588
# test at the command level without loading the whole test suite
3589
out, err = self.run_bzr(('selftest', '--list') + selftest_args)
3590
actual = out.splitlines()
3591
self.assertEquals(expected, actual)
3593
def test_full_list(self):
3594
self.assertTestList(['a', 'b', 'c'])
3596
def test_single_exclude(self):
3597
self.assertTestList(['b', 'c'], '-x', 'a')
3599
def test_mutiple_excludes(self):
3600
self.assertTestList(['c'], '-x', 'a', '-x', 'b')
3603
class TestCounterHooks(tests.TestCase, SelfTestHelper):
3605
_test_needs_features = [features.subunit]
3608
super(TestCounterHooks, self).setUp()
3609
class Test(tests.TestCase):
3612
super(Test, self).setUp()
3613
self.hooks = hooks.Hooks()
3614
self.hooks.add_hook('myhook', 'Foo bar blah', (2,4))
3615
self.install_counter_hook(self.hooks, 'myhook')
3620
def run_hook_once(self):
3621
for hook in self.hooks['myhook']:
3624
self.test_class = Test
3626
def assertHookCalls(self, expected_calls, test_name):
3627
test = self.test_class(test_name)
3628
result = unittest.TestResult()
3630
self.assertTrue(hasattr(test, '_counters'))
3631
self.assertTrue(test._counters.has_key('myhook'))
3632
self.assertEquals(expected_calls, test._counters['myhook'])
3634
def test_no_hook(self):
3635
self.assertHookCalls(0, 'no_hook')
3637
def test_run_hook_once(self):
3638
tt = features.testtools
3639
if tt.module.__version__ < (0, 9, 8):
3640
raise tests.TestSkipped('testtools-0.9.8 required for addDetail')
3641
self.assertHookCalls(1, 'run_hook_once')