1655
1659
test.run(unittest.TestResult())
1656
1660
self.assertEqual('original', obj.test_attr)
1662
def test_recordCalls(self):
1663
from bzrlib.tests import test_selftest
1664
calls = self.recordCalls(
1665
test_selftest, '_add_numbers')
1666
self.assertEqual(test_selftest._add_numbers(2, 10),
1668
self.assertEquals(calls, [((2, 10), {})])
1671
def _add_numbers(a, b):
1675
class _MissingFeature(features.Feature):
1678
missing_feature = _MissingFeature()
1681
def _get_test(name):
1682
"""Get an instance of a specific example test.
1684
We protect this in a function so that they don't auto-run in the test
1688
class ExampleTests(tests.TestCase):
1690
def test_fail(self):
1691
mutter('this was a failing test')
1692
self.fail('this test will fail')
1694
def test_error(self):
1695
mutter('this test errored')
1696
raise RuntimeError('gotcha')
1698
def test_missing_feature(self):
1699
mutter('missing the feature')
1700
self.requireFeature(missing_feature)
1702
def test_skip(self):
1703
mutter('this test will be skipped')
1704
raise tests.TestSkipped('reason')
1706
def test_success(self):
1707
mutter('this test succeeds')
1709
def test_xfail(self):
1710
mutter('test with expected failure')
1711
self.knownFailure('this_fails')
1713
def test_unexpected_success(self):
1714
mutter('test with unexpected success')
1715
self.expectFailure('should_fail', lambda: None)
1717
return ExampleTests(name)
1720
class TestTestCaseLogDetails(tests.TestCase):
1722
def _run_test(self, test_name):
1723
test = _get_test(test_name)
1724
result = testtools.TestResult()
1728
def test_fail_has_log(self):
1729
result = self._run_test('test_fail')
1730
self.assertEqual(1, len(result.failures))
1731
result_content = result.failures[0][1]
1732
self.assertContainsRe(result_content,
1733
'(?m)^(?:Text attachment: )?log(?:$|: )')
1734
self.assertContainsRe(result_content, 'this was a failing test')
1736
def test_error_has_log(self):
1737
result = self._run_test('test_error')
1738
self.assertEqual(1, len(result.errors))
1739
result_content = result.errors[0][1]
1740
self.assertContainsRe(result_content,
1741
'(?m)^(?:Text attachment: )?log(?:$|: )')
1742
self.assertContainsRe(result_content, 'this test errored')
1744
def test_skip_has_no_log(self):
1745
result = self._run_test('test_skip')
1746
self.assertEqual(['reason'], result.skip_reasons.keys())
1747
skips = result.skip_reasons['reason']
1748
self.assertEqual(1, len(skips))
1750
self.assertFalse('log' in test.getDetails())
1752
def test_missing_feature_has_no_log(self):
1753
# testtools doesn't know about addNotSupported, so it just gets
1754
# considered as a skip
1755
result = self._run_test('test_missing_feature')
1756
self.assertEqual([missing_feature], result.skip_reasons.keys())
1757
skips = result.skip_reasons[missing_feature]
1758
self.assertEqual(1, len(skips))
1760
self.assertFalse('log' in test.getDetails())
1762
def test_xfail_has_no_log(self):
1763
result = self._run_test('test_xfail')
1764
self.assertEqual(1, len(result.expectedFailures))
1765
result_content = result.expectedFailures[0][1]
1766
self.assertNotContainsRe(result_content,
1767
'(?m)^(?:Text attachment: )?log(?:$|: )')
1768
self.assertNotContainsRe(result_content, 'test with expected failure')
1770
def test_unexpected_success_has_log(self):
1771
result = self._run_test('test_unexpected_success')
1772
self.assertEqual(1, len(result.unexpectedSuccesses))
1773
# Inconsistency, unexpectedSuccesses is a list of tests,
1774
# expectedFailures is a list of reasons?
1775
test = result.unexpectedSuccesses[0]
1776
details = test.getDetails()
1777
self.assertTrue('log' in details)
1780
class TestTestCloning(tests.TestCase):
1781
"""Tests that test cloning of TestCases (as used by multiply_tests)."""
1783
def test_cloned_testcase_does_not_share_details(self):
1784
"""A TestCase cloned with clone_test does not share mutable attributes
1785
such as details or cleanups.
1787
class Test(tests.TestCase):
1789
self.addDetail('foo', Content('text/plain', lambda: 'foo'))
1790
orig_test = Test('test_foo')
1791
cloned_test = tests.clone_test(orig_test, orig_test.id() + '(cloned)')
1792
orig_test.run(unittest.TestResult())
1793
self.assertEqual('foo', orig_test.getDetails()['foo'].iter_bytes())
1794
self.assertEqual(None, cloned_test.getDetails().get('foo'))
1796
def test_double_apply_scenario_preserves_first_scenario(self):
1797
"""Applying two levels of scenarios to a test preserves the attributes
1798
added by both scenarios.
1800
class Test(tests.TestCase):
1803
test = Test('test_foo')
1804
scenarios_x = [('x=1', {'x': 1}), ('x=2', {'x': 2})]
1805
scenarios_y = [('y=1', {'y': 1}), ('y=2', {'y': 2})]
1806
suite = tests.multiply_tests(test, scenarios_x, unittest.TestSuite())
1807
suite = tests.multiply_tests(suite, scenarios_y, unittest.TestSuite())
1808
all_tests = list(tests.iter_suite_tests(suite))
1809
self.assertLength(4, all_tests)
1810
all_xys = sorted((t.x, t.y) for t in all_tests)
1811
self.assertEqual([(1, 1), (1, 2), (2, 1), (2, 2)], all_xys)
1659
1814
# NB: Don't delete this; it's not actually from 0.11!
1660
1815
@deprecated_function(deprecated_in((0, 11, 0)))
1972
2124
load_list='missing file name', list_only=True)
2127
class TestSubunitLogDetails(tests.TestCase, SelfTestHelper):
2129
_test_needs_features = [features.subunit]
2131
def run_subunit_stream(self, test_name):
2132
from subunit import ProtocolTestCase
2134
return TestUtil.TestSuite([_get_test(test_name)])
2135
stream = self.run_selftest(runner_class=tests.SubUnitBzrRunner,
2136
test_suite_factory=factory)
2137
test = ProtocolTestCase(stream)
2138
result = testtools.TestResult()
2140
content = stream.getvalue()
2141
return content, result
2143
def test_fail_has_log(self):
2144
content, result = self.run_subunit_stream('test_fail')
2145
self.assertEqual(1, len(result.failures))
2146
self.assertContainsRe(content, '(?m)^log$')
2147
self.assertContainsRe(content, 'this test will fail')
2149
def test_error_has_log(self):
2150
content, result = self.run_subunit_stream('test_error')
2151
self.assertContainsRe(content, '(?m)^log$')
2152
self.assertContainsRe(content, 'this test errored')
2154
def test_skip_has_no_log(self):
2155
content, result = self.run_subunit_stream('test_skip')
2156
self.assertNotContainsRe(content, '(?m)^log$')
2157
self.assertNotContainsRe(content, 'this test will be skipped')
2158
self.assertEqual(['reason'], result.skip_reasons.keys())
2159
skips = result.skip_reasons['reason']
2160
self.assertEqual(1, len(skips))
2162
# RemotedTestCase doesn't preserve the "details"
2163
## self.assertFalse('log' in test.getDetails())
2165
def test_missing_feature_has_no_log(self):
2166
content, result = self.run_subunit_stream('test_missing_feature')
2167
self.assertNotContainsRe(content, '(?m)^log$')
2168
self.assertNotContainsRe(content, 'missing the feature')
2169
self.assertEqual(['_MissingFeature\n'], result.skip_reasons.keys())
2170
skips = result.skip_reasons['_MissingFeature\n']
2171
self.assertEqual(1, len(skips))
2173
# RemotedTestCase doesn't preserve the "details"
2174
## self.assertFalse('log' in test.getDetails())
2176
def test_xfail_has_no_log(self):
2177
content, result = self.run_subunit_stream('test_xfail')
2178
self.assertNotContainsRe(content, '(?m)^log$')
2179
self.assertNotContainsRe(content, 'test with expected failure')
2180
self.assertEqual(1, len(result.expectedFailures))
2181
result_content = result.expectedFailures[0][1]
2182
self.assertNotContainsRe(result_content,
2183
'(?m)^(?:Text attachment: )?log(?:$|: )')
2184
self.assertNotContainsRe(result_content, 'test with expected failure')
2186
def test_unexpected_success_has_log(self):
2187
content, result = self.run_subunit_stream('test_unexpected_success')
2188
self.assertContainsRe(content, '(?m)^log$')
2189
self.assertContainsRe(content, 'test with unexpected success')
2190
# GZ 2011-05-18: Old versions of subunit treat unexpected success as a
2191
# success, if a min version check is added remove this
2192
from subunit import TestProtocolClient as _Client
2193
if _Client.addUnexpectedSuccess.im_func is _Client.addSuccess.im_func:
2194
self.expectFailure('subunit treats "unexpectedSuccess"'
2195
' as a plain success',
2196
self.assertEqual, 1, len(result.unexpectedSuccesses))
2197
self.assertEqual(1, len(result.unexpectedSuccesses))
2198
test = result.unexpectedSuccesses[0]
2199
# RemotedTestCase doesn't preserve the "details"
2200
## self.assertTrue('log' in test.getDetails())
2202
def test_success_has_no_log(self):
2203
content, result = self.run_subunit_stream('test_success')
2204
self.assertEqual(1, result.testsRun)
2205
self.assertNotContainsRe(content, '(?m)^log$')
2206
self.assertNotContainsRe(content, 'this test succeeds')
1975
2209
class TestRunBzr(tests.TestCase):
2363
2598
self.assertEqual('bzr: interrupted\n', result[1])
2366
class TestFeature(tests.TestCase):
2368
def test_caching(self):
2369
"""Feature._probe is called by the feature at most once."""
2370
class InstrumentedFeature(tests.Feature):
2372
super(InstrumentedFeature, self).__init__()
2375
self.calls.append('_probe')
2377
feature = InstrumentedFeature()
2379
self.assertEqual(['_probe'], feature.calls)
2381
self.assertEqual(['_probe'], feature.calls)
2383
def test_named_str(self):
2384
"""Feature.__str__ should thunk to feature_name()."""
2385
class NamedFeature(tests.Feature):
2386
def feature_name(self):
2388
feature = NamedFeature()
2389
self.assertEqual('symlinks', str(feature))
2391
def test_default_str(self):
2392
"""Feature.__str__ should default to __class__.__name__."""
2393
class NamedFeature(tests.Feature):
2395
feature = NamedFeature()
2396
self.assertEqual('NamedFeature', str(feature))
2399
class TestUnavailableFeature(tests.TestCase):
2401
def test_access_feature(self):
2402
feature = tests.Feature()
2403
exception = tests.UnavailableFeature(feature)
2404
self.assertIs(feature, exception.args[0])
2407
simple_thunk_feature = tests._CompatabilityThunkFeature(
2408
deprecated_in((2, 1, 0)),
2409
'bzrlib.tests.test_selftest',
2410
'simple_thunk_feature','UnicodeFilename',
2411
replacement_module='bzrlib.tests'
2414
class Test_CompatibilityFeature(tests.TestCase):
2416
def test_does_thunk(self):
2417
res = self.callDeprecated(
2418
['bzrlib.tests.test_selftest.simple_thunk_feature was deprecated'
2419
' in version 2.1.0. Use bzrlib.tests.UnicodeFilename instead.'],
2420
simple_thunk_feature.available)
2421
self.assertEqual(tests.UnicodeFilename.available(), res)
2424
class TestModuleAvailableFeature(tests.TestCase):
2426
def test_available_module(self):
2427
feature = tests.ModuleAvailableFeature('bzrlib.tests')
2428
self.assertEqual('bzrlib.tests', feature.module_name)
2429
self.assertEqual('bzrlib.tests', str(feature))
2430
self.assertTrue(feature.available())
2431
self.assertIs(tests, feature.module)
2433
def test_unavailable_module(self):
2434
feature = tests.ModuleAvailableFeature('bzrlib.no_such_module_exists')
2435
self.assertEqual('bzrlib.no_such_module_exists', str(feature))
2436
self.assertFalse(feature.available())
2437
self.assertIs(None, feature.module)
2440
2601
class TestSelftestFiltering(tests.TestCase):
2442
2603
def setUp(self):
2966
3128
self.assertEquals('bzrlib.plugins', tpr.resolve_alias('bp'))
3131
class TestThreadLeakDetection(tests.TestCase):
3132
"""Ensure when tests leak threads we detect and report it"""
3134
class LeakRecordingResult(tests.ExtendedTestResult):
3136
tests.ExtendedTestResult.__init__(self, StringIO(), 0, 1)
3138
def _report_thread_leak(self, test, leaks, alive):
3139
self.leaks.append((test, leaks))
3141
def test_testcase_without_addCleanups(self):
3142
"""Check old TestCase instances don't break with leak detection"""
3143
class Test(unittest.TestCase):
3146
result = self.LeakRecordingResult()
3148
result.startTestRun()
3150
result.stopTestRun()
3151
self.assertEqual(result._tests_leaking_threads_count, 0)
3152
self.assertEqual(result.leaks, [])
3154
def test_thread_leak(self):
3155
"""Ensure a thread that outlives the running of a test is reported
3157
Uses a thread that blocks on an event, and is started by the inner
3158
test case. As the thread outlives the inner case's run, it should be
3159
detected as a leak, but the event is then set so that the thread can
3160
be safely joined in cleanup so it's not leaked for real.
3162
event = threading.Event()
3163
thread = threading.Thread(name="Leaker", target=event.wait)
3164
class Test(tests.TestCase):
3165
def test_leak(self):
3167
result = self.LeakRecordingResult()
3168
test = Test("test_leak")
3169
self.addCleanup(thread.join)
3170
self.addCleanup(event.set)
3171
result.startTestRun()
3173
result.stopTestRun()
3174
self.assertEqual(result._tests_leaking_threads_count, 1)
3175
self.assertEqual(result._first_thread_leaker_id, test.id())
3176
self.assertEqual(result.leaks, [(test, set([thread]))])
3177
self.assertContainsString(result.stream.getvalue(), "leaking threads")
3179
def test_multiple_leaks(self):
3180
"""Check multiple leaks are blamed on the test cases at fault
3182
Same concept as the previous test, but has one inner test method that
3183
leaks two threads, and one that doesn't leak at all.
3185
event = threading.Event()
3186
thread_a = threading.Thread(name="LeakerA", target=event.wait)
3187
thread_b = threading.Thread(name="LeakerB", target=event.wait)
3188
thread_c = threading.Thread(name="LeakerC", target=event.wait)
3189
class Test(tests.TestCase):
3190
def test_first_leak(self):
3192
def test_second_no_leak(self):
3194
def test_third_leak(self):
3197
result = self.LeakRecordingResult()
3198
first_test = Test("test_first_leak")
3199
third_test = Test("test_third_leak")
3200
self.addCleanup(thread_a.join)
3201
self.addCleanup(thread_b.join)
3202
self.addCleanup(thread_c.join)
3203
self.addCleanup(event.set)
3204
result.startTestRun()
3206
[first_test, Test("test_second_no_leak"), third_test]
3208
result.stopTestRun()
3209
self.assertEqual(result._tests_leaking_threads_count, 2)
3210
self.assertEqual(result._first_thread_leaker_id, first_test.id())
3211
self.assertEqual(result.leaks, [
3212
(first_test, set([thread_b])),
3213
(third_test, set([thread_a, thread_c]))])
3214
self.assertContainsString(result.stream.getvalue(), "leaking threads")
3217
class TestPostMortemDebugging(tests.TestCase):
3218
"""Check post mortem debugging works when tests fail or error"""
3220
class TracebackRecordingResult(tests.ExtendedTestResult):
3222
tests.ExtendedTestResult.__init__(self, StringIO(), 0, 1)
3223
self.postcode = None
3224
def _post_mortem(self, tb=None):
3225
"""Record the code object at the end of the current traceback"""
3226
tb = tb or sys.exc_info()[2]
3229
while next is not None:
3232
self.postcode = tb.tb_frame.f_code
3233
def report_error(self, test, err):
3235
def report_failure(self, test, err):
3238
def test_location_unittest_error(self):
3239
"""Needs right post mortem traceback with erroring unittest case"""
3240
class Test(unittest.TestCase):
3243
result = self.TracebackRecordingResult()
3245
self.assertEqual(result.postcode, Test.runTest.func_code)
3247
def test_location_unittest_failure(self):
3248
"""Needs right post mortem traceback with failing unittest case"""
3249
class Test(unittest.TestCase):
3251
raise self.failureException
3252
result = self.TracebackRecordingResult()
3254
self.assertEqual(result.postcode, Test.runTest.func_code)
3256
def test_location_bt_error(self):
3257
"""Needs right post mortem traceback with erroring bzrlib.tests case"""
3258
class Test(tests.TestCase):
3259
def test_error(self):
3261
result = self.TracebackRecordingResult()
3262
Test("test_error").run(result)
3263
self.assertEqual(result.postcode, Test.test_error.func_code)
3265
def test_location_bt_failure(self):
3266
"""Needs right post mortem traceback with failing bzrlib.tests case"""
3267
class Test(tests.TestCase):
3268
def test_failure(self):
3269
raise self.failureException
3270
result = self.TracebackRecordingResult()
3271
Test("test_failure").run(result)
3272
self.assertEqual(result.postcode, Test.test_failure.func_code)
3274
def test_env_var_triggers_post_mortem(self):
3275
"""Check pdb.post_mortem is called iff BZR_TEST_PDB is set"""
3277
result = tests.ExtendedTestResult(StringIO(), 0, 1)
3278
post_mortem_calls = []
3279
self.overrideAttr(pdb, "post_mortem", post_mortem_calls.append)
3280
self.overrideEnv('BZR_TEST_PDB', None)
3281
result._post_mortem(1)
3282
self.overrideEnv('BZR_TEST_PDB', 'on')
3283
result._post_mortem(2)
3284
self.assertEqual([2], post_mortem_calls)
2969
3287
class TestRunSuite(tests.TestCase):
2971
3289
def test_runner_class(self):
2982
3300
self.verbosity)
2983
3301
tests.run_suite(suite, runner_class=MyRunner, stream=StringIO())
2984
3302
self.assertLength(1, calls)
3305
class _Selftest(object):
3306
"""Mixin for tests needing full selftest output"""
3308
def _inject_stream_into_subunit(self, stream):
3309
"""To be overridden by subclasses that run tests out of process"""
3311
def _run_selftest(self, **kwargs):
3313
self._inject_stream_into_subunit(sio)
3314
tests.selftest(stream=sio, stop_on_failure=False, **kwargs)
3315
return sio.getvalue()
3318
class _ForkedSelftest(_Selftest):
3319
"""Mixin for tests needing full selftest output with forked children"""
3321
_test_needs_features = [features.subunit]
3323
def _inject_stream_into_subunit(self, stream):
3324
"""Monkey-patch subunit so the extra output goes to stream not stdout
3326
Some APIs need rewriting so this kind of bogus hackery can be replaced
3327
by passing the stream param from run_tests down into ProtocolTestCase.
3329
from subunit import ProtocolTestCase
3330
_original_init = ProtocolTestCase.__init__
3331
def _init_with_passthrough(self, *args, **kwargs):
3332
_original_init(self, *args, **kwargs)
3333
self._passthrough = stream
3334
self.overrideAttr(ProtocolTestCase, "__init__", _init_with_passthrough)
3336
def _run_selftest(self, **kwargs):
3337
# GZ 2011-05-26: Add a PosixSystem feature so this check can go away
3338
if getattr(os, "fork", None) is None:
3339
raise tests.TestNotApplicable("Platform doesn't support forking")
3340
# Make sure the fork code is actually invoked by claiming two cores
3341
self.overrideAttr(osutils, "local_concurrency", lambda: 2)
3342
kwargs.setdefault("suite_decorators", []).append(tests.fork_decorator)
3343
return super(_ForkedSelftest, self)._run_selftest(**kwargs)
3346
class TestParallelFork(_ForkedSelftest, tests.TestCase):
3347
"""Check operation of --parallel=fork selftest option"""
3349
def test_error_in_child_during_fork(self):
3350
"""Error in a forked child during test setup should get reported"""
3351
class Test(tests.TestCase):
3352
def testMethod(self):
3354
# We don't care what, just break something that a child will run
3355
self.overrideAttr(tests, "workaround_zealous_crypto_random", None)
3356
out = self._run_selftest(test_suite_factory=Test)
3357
# Lines from the tracebacks of the two child processes may be mixed
3358
# together due to the way subunit parses and forwards the streams,
3359
# so permit extra lines between each part of the error output.
3360
self.assertContainsRe(out,
3363
".+ in fork_for_tests\n"
3365
"\s*workaround_zealous_crypto_random\(\)\n"
3370
class TestUncollectedWarnings(_Selftest, tests.TestCase):
3371
"""Check a test case still alive after being run emits a warning"""
3373
class Test(tests.TestCase):
3374
def test_pass(self):
3376
def test_self_ref(self):
3377
self.also_self = self.test_self_ref
3378
def test_skip(self):
3379
self.skip("Don't need")
3381
def _get_suite(self):
3382
return TestUtil.TestSuite([
3383
self.Test("test_pass"),
3384
self.Test("test_self_ref"),
3385
self.Test("test_skip"),
3388
def _run_selftest_with_suite(self, **kwargs):
3389
old_flags = tests.selftest_debug_flags
3390
tests.selftest_debug_flags = old_flags.union(["uncollected_cases"])
3391
gc_on = gc.isenabled()
3395
output = self._run_selftest(test_suite_factory=self._get_suite,
3400
tests.selftest_debug_flags = old_flags
3401
self.assertNotContainsRe(output, "Uncollected test case.*test_pass")
3402
self.assertContainsRe(output, "Uncollected test case.*test_self_ref")
3405
def test_testsuite(self):
3406
self._run_selftest_with_suite()
3408
def test_pattern(self):
3409
out = self._run_selftest_with_suite(pattern="test_(?:pass|self_ref)$")
3410
self.assertNotContainsRe(out, "test_skip")
3412
def test_exclude_pattern(self):
3413
out = self._run_selftest_with_suite(exclude_pattern="test_skip$")
3414
self.assertNotContainsRe(out, "test_skip")
3416
def test_random_seed(self):
3417
self._run_selftest_with_suite(random_seed="now")
3419
def test_matching_tests_first(self):
3420
self._run_selftest_with_suite(matching_tests_first=True,
3421
pattern="test_self_ref$")
3423
def test_starting_with_and_exclude(self):
3424
out = self._run_selftest_with_suite(starting_with=["bt."],
3425
exclude_pattern="test_skip$")
3426
self.assertNotContainsRe(out, "test_skip")
3428
def test_additonal_decorator(self):
3429
out = self._run_selftest_with_suite(
3430
suite_decorators=[tests.TestDecorator])
3433
class TestUncollectedWarningsSubunit(TestUncollectedWarnings):
3434
"""Check warnings from tests staying alive are emitted with subunit"""
3436
_test_needs_features = [features.subunit]
3438
def _run_selftest_with_suite(self, **kwargs):
3439
return TestUncollectedWarnings._run_selftest_with_suite(self,
3440
runner_class=tests.SubUnitBzrRunner, **kwargs)
3443
class TestUncollectedWarningsForked(_ForkedSelftest, TestUncollectedWarnings):
3444
"""Check warnings from tests staying alive are emitted when forking"""
3447
class TestEnvironHandling(tests.TestCase):
3449
def test_overrideEnv_None_called_twice_doesnt_leak(self):
3450
self.assertFalse('MYVAR' in os.environ)
3451
self.overrideEnv('MYVAR', '42')
3452
# We use an embedded test to make sure we fix the _captureVar bug
3453
class Test(tests.TestCase):
3455
# The first call save the 42 value
3456
self.overrideEnv('MYVAR', None)
3457
self.assertEquals(None, os.environ.get('MYVAR'))
3458
# Make sure we can call it twice
3459
self.overrideEnv('MYVAR', None)
3460
self.assertEquals(None, os.environ.get('MYVAR'))
3462
result = tests.TextTestResult(output, 0, 1)
3463
Test('test_me').run(result)
3464
if not result.wasStrictlySuccessful():
3465
self.fail(output.getvalue())
3466
# We get our value back
3467
self.assertEquals('42', os.environ.get('MYVAR'))
3470
class TestIsolatedEnv(tests.TestCase):
3471
"""Test isolating tests from os.environ.
3473
Since we use tests that are already isolated from os.environ a bit of care
3474
should be taken when designing the tests to avoid bootstrap side-effects.
3475
The tests start an already clean os.environ which allow doing valid
3476
assertions about which variables are present or not and design tests around
3480
class ScratchMonkey(tests.TestCase):
3485
def test_basics(self):
3486
# Make sure we know the definition of BZR_HOME: not part of os.environ
3487
# for tests.TestCase.
3488
self.assertTrue('BZR_HOME' in tests.isolated_environ)
3489
self.assertEquals(None, tests.isolated_environ['BZR_HOME'])
3490
# Being part of isolated_environ, BZR_HOME should not appear here
3491
self.assertFalse('BZR_HOME' in os.environ)
3492
# Make sure we know the definition of LINES: part of os.environ for
3494
self.assertTrue('LINES' in tests.isolated_environ)
3495
self.assertEquals('25', tests.isolated_environ['LINES'])
3496
self.assertEquals('25', os.environ['LINES'])
3498
def test_injecting_unknown_variable(self):
3499
# BZR_HOME is known to be absent from os.environ
3500
test = self.ScratchMonkey('test_me')
3501
tests.override_os_environ(test, {'BZR_HOME': 'foo'})
3502
self.assertEquals('foo', os.environ['BZR_HOME'])
3503
tests.restore_os_environ(test)
3504
self.assertFalse('BZR_HOME' in os.environ)
3506
def test_injecting_known_variable(self):
3507
test = self.ScratchMonkey('test_me')
3508
# LINES is known to be present in os.environ
3509
tests.override_os_environ(test, {'LINES': '42'})
3510
self.assertEquals('42', os.environ['LINES'])
3511
tests.restore_os_environ(test)
3512
self.assertEquals('25', os.environ['LINES'])
3514
def test_deleting_variable(self):
3515
test = self.ScratchMonkey('test_me')
3516
# LINES is known to be present in os.environ
3517
tests.override_os_environ(test, {'LINES': None})
3518
self.assertTrue('LINES' not in os.environ)
3519
tests.restore_os_environ(test)
3520
self.assertEquals('25', os.environ['LINES'])
3523
class TestDocTestSuiteIsolation(tests.TestCase):
3524
"""Test that `tests.DocTestSuite` isolates doc tests from os.environ.
3526
Since tests.TestCase alreay provides an isolation from os.environ, we use
3527
the clean environment as a base for testing. To precisely capture the
3528
isolation provided by tests.DocTestSuite, we use doctest.DocTestSuite to
3531
We want to make sure `tests.DocTestSuite` respect `tests.isolated_environ`,
3532
not `os.environ` so each test overrides it to suit its needs.
3536
def get_doctest_suite_for_string(self, klass, string):
3537
class Finder(doctest.DocTestFinder):
3539
def find(*args, **kwargs):
3540
test = doctest.DocTestParser().get_doctest(
3541
string, {}, 'foo', 'foo.py', 0)
3544
suite = klass(test_finder=Finder())
3547
def run_doctest_suite_for_string(self, klass, string):
3548
suite = self.get_doctest_suite_for_string(klass, string)
3550
result = tests.TextTestResult(output, 0, 1)
3552
return result, output
3554
def assertDocTestStringSucceds(self, klass, string):
3555
result, output = self.run_doctest_suite_for_string(klass, string)
3556
if not result.wasStrictlySuccessful():
3557
self.fail(output.getvalue())
3559
def assertDocTestStringFails(self, klass, string):
3560
result, output = self.run_doctest_suite_for_string(klass, string)
3561
if result.wasStrictlySuccessful():
3562
self.fail(output.getvalue())
3564
def test_injected_variable(self):
3565
self.overrideAttr(tests, 'isolated_environ', {'LINES': '42'})
3568
>>> os.environ['LINES']
3571
# doctest.DocTestSuite fails as it sees '25'
3572
self.assertDocTestStringFails(doctest.DocTestSuite, test)
3573
# tests.DocTestSuite sees '42'
3574
self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
3576
def test_deleted_variable(self):
3577
self.overrideAttr(tests, 'isolated_environ', {'LINES': None})
3580
>>> os.environ.get('LINES')
3582
# doctest.DocTestSuite fails as it sees '25'
3583
self.assertDocTestStringFails(doctest.DocTestSuite, test)
3584
# tests.DocTestSuite sees None
3585
self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
3588
class TestSelftestExcludePatterns(tests.TestCase):
3591
super(TestSelftestExcludePatterns, self).setUp()
3592
self.overrideAttr(tests, 'test_suite', self.suite_factory)
3594
def suite_factory(self, keep_only=None, starting_with=None):
3595
"""A test suite factory with only a few tests."""
3596
class Test(tests.TestCase):
3598
# We don't need the full class path
3599
return self._testMethodName
3606
return TestUtil.TestSuite([Test("a"), Test("b"), Test("c")])
3608
def assertTestList(self, expected, *selftest_args):
3609
# We rely on setUp installing the right test suite factory so we can
3610
# test at the command level without loading the whole test suite
3611
out, err = self.run_bzr(('selftest', '--list') + selftest_args)
3612
actual = out.splitlines()
3613
self.assertEquals(expected, actual)
3615
def test_full_list(self):
3616
self.assertTestList(['a', 'b', 'c'])
3618
def test_single_exclude(self):
3619
self.assertTestList(['b', 'c'], '-x', 'a')
3621
def test_mutiple_excludes(self):
3622
self.assertTestList(['c'], '-x', 'a', '-x', 'b')
3625
class TestCounterHooks(tests.TestCase, SelfTestHelper):
3627
_test_needs_features = [features.subunit]
3630
super(TestCounterHooks, self).setUp()
3631
class Test(tests.TestCase):
3634
super(Test, self).setUp()
3635
self.hooks = hooks.Hooks()
3636
self.hooks.add_hook('myhook', 'Foo bar blah', (2,4))
3637
self.install_counter_hook(self.hooks, 'myhook')
3642
def run_hook_once(self):
3643
for hook in self.hooks['myhook']:
3646
self.test_class = Test
3648
def assertHookCalls(self, expected_calls, test_name):
3649
test = self.test_class(test_name)
3650
result = unittest.TestResult()
3652
self.assertTrue(hasattr(test, '_counters'))
3653
self.assertTrue(test._counters.has_key('myhook'))
3654
self.assertEquals(expected_calls, test._counters['myhook'])
3656
def test_no_hook(self):
3657
self.assertHookCalls(0, 'no_hook')
3659
def test_run_hook_once(self):
3660
tt = features.testtools
3661
if tt.module.__version__ < (0, 9, 8):
3662
raise tests.TestSkipped('testtools-0.9.8 required for addDetail')
3663
self.assertHookCalls(1, 'run_hook_once')