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