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()
1654
1684
test.run(unittest.TestResult())
1655
1685
self.assertEqual('original', obj.test_attr)
1687
def test_recordCalls(self):
1688
from bzrlib.tests import test_selftest
1689
calls = self.recordCalls(
1690
test_selftest, '_add_numbers')
1691
self.assertEqual(test_selftest._add_numbers(2, 10),
1693
self.assertEquals(calls, [((2, 10), {})])
1696
def _add_numbers(a, b):
1700
class _MissingFeature(tests.Feature):
1703
missing_feature = _MissingFeature()
1706
def _get_test(name):
1707
"""Get an instance of a specific example test.
1709
We protect this in a function so that they don't auto-run in the test
1713
class ExampleTests(tests.TestCase):
1715
def test_fail(self):
1716
mutter('this was a failing test')
1717
self.fail('this test will fail')
1719
def test_error(self):
1720
mutter('this test errored')
1721
raise RuntimeError('gotcha')
1723
def test_missing_feature(self):
1724
mutter('missing the feature')
1725
self.requireFeature(missing_feature)
1727
def test_skip(self):
1728
mutter('this test will be skipped')
1729
raise tests.TestSkipped('reason')
1731
def test_success(self):
1732
mutter('this test succeeds')
1734
def test_xfail(self):
1735
mutter('test with expected failure')
1736
self.knownFailure('this_fails')
1738
def test_unexpected_success(self):
1739
mutter('test with unexpected success')
1740
self.expectFailure('should_fail', lambda: None)
1742
return ExampleTests(name)
1745
class TestTestCaseLogDetails(tests.TestCase):
1747
def _run_test(self, test_name):
1748
test = _get_test(test_name)
1749
result = testtools.TestResult()
1753
def test_fail_has_log(self):
1754
result = self._run_test('test_fail')
1755
self.assertEqual(1, len(result.failures))
1756
result_content = result.failures[0][1]
1757
self.assertContainsRe(result_content, 'Text attachment: log')
1758
self.assertContainsRe(result_content, 'this was a failing test')
1760
def test_error_has_log(self):
1761
result = self._run_test('test_error')
1762
self.assertEqual(1, len(result.errors))
1763
result_content = result.errors[0][1]
1764
self.assertContainsRe(result_content, 'Text attachment: log')
1765
self.assertContainsRe(result_content, 'this test errored')
1767
def test_skip_has_no_log(self):
1768
result = self._run_test('test_skip')
1769
self.assertEqual(['reason'], result.skip_reasons.keys())
1770
skips = result.skip_reasons['reason']
1771
self.assertEqual(1, len(skips))
1773
self.assertFalse('log' in test.getDetails())
1775
def test_missing_feature_has_no_log(self):
1776
# testtools doesn't know about addNotSupported, so it just gets
1777
# considered as a skip
1778
result = self._run_test('test_missing_feature')
1779
self.assertEqual([missing_feature], result.skip_reasons.keys())
1780
skips = result.skip_reasons[missing_feature]
1781
self.assertEqual(1, len(skips))
1783
self.assertFalse('log' in test.getDetails())
1785
def test_xfail_has_no_log(self):
1786
result = self._run_test('test_xfail')
1787
self.assertEqual(1, len(result.expectedFailures))
1788
result_content = result.expectedFailures[0][1]
1789
self.assertNotContainsRe(result_content, 'Text attachment: log')
1790
self.assertNotContainsRe(result_content, 'test with expected failure')
1792
def test_unexpected_success_has_log(self):
1793
result = self._run_test('test_unexpected_success')
1794
self.assertEqual(1, len(result.unexpectedSuccesses))
1795
# Inconsistency, unexpectedSuccesses is a list of tests,
1796
# expectedFailures is a list of reasons?
1797
test = result.unexpectedSuccesses[0]
1798
details = test.getDetails()
1799
self.assertTrue('log' in details)
1802
class TestTestCloning(tests.TestCase):
1803
"""Tests that test cloning of TestCases (as used by multiply_tests)."""
1805
def test_cloned_testcase_does_not_share_details(self):
1806
"""A TestCase cloned with clone_test does not share mutable attributes
1807
such as details or cleanups.
1809
class Test(tests.TestCase):
1811
self.addDetail('foo', Content('text/plain', lambda: 'foo'))
1812
orig_test = Test('test_foo')
1813
cloned_test = tests.clone_test(orig_test, orig_test.id() + '(cloned)')
1814
orig_test.run(unittest.TestResult())
1815
self.assertEqual('foo', orig_test.getDetails()['foo'].iter_bytes())
1816
self.assertEqual(None, cloned_test.getDetails().get('foo'))
1818
def test_double_apply_scenario_preserves_first_scenario(self):
1819
"""Applying two levels of scenarios to a test preserves the attributes
1820
added by both scenarios.
1822
class Test(tests.TestCase):
1825
test = Test('test_foo')
1826
scenarios_x = [('x=1', {'x': 1}), ('x=2', {'x': 2})]
1827
scenarios_y = [('y=1', {'y': 1}), ('y=2', {'y': 2})]
1828
suite = tests.multiply_tests(test, scenarios_x, unittest.TestSuite())
1829
suite = tests.multiply_tests(suite, scenarios_y, unittest.TestSuite())
1830
all_tests = list(tests.iter_suite_tests(suite))
1831
self.assertLength(4, all_tests)
1832
all_xys = sorted((t.x, t.y) for t in all_tests)
1833
self.assertEqual([(1, 1), (1, 2), (2, 1), (2, 2)], all_xys)
1658
1836
# NB: Don't delete this; it's not actually from 0.11!
1659
1837
@deprecated_function(deprecated_in((0, 11, 0)))
1971
2146
load_list='missing file name', list_only=True)
2149
class TestSubunitLogDetails(tests.TestCase, SelfTestHelper):
2151
_test_needs_features = [features.subunit]
2153
def run_subunit_stream(self, test_name):
2154
from subunit import ProtocolTestCase
2156
return TestUtil.TestSuite([_get_test(test_name)])
2157
stream = self.run_selftest(runner_class=tests.SubUnitBzrRunner,
2158
test_suite_factory=factory)
2159
test = ProtocolTestCase(stream)
2160
result = testtools.TestResult()
2162
content = stream.getvalue()
2163
return content, result
2165
def test_fail_has_log(self):
2166
content, result = self.run_subunit_stream('test_fail')
2167
self.assertEqual(1, len(result.failures))
2168
self.assertContainsRe(content, '(?m)^log$')
2169
self.assertContainsRe(content, 'this test will fail')
2171
def test_error_has_log(self):
2172
content, result = self.run_subunit_stream('test_error')
2173
self.assertContainsRe(content, '(?m)^log$')
2174
self.assertContainsRe(content, 'this test errored')
2176
def test_skip_has_no_log(self):
2177
content, result = self.run_subunit_stream('test_skip')
2178
self.assertNotContainsRe(content, '(?m)^log$')
2179
self.assertNotContainsRe(content, 'this test will be skipped')
2180
self.assertEqual(['reason'], result.skip_reasons.keys())
2181
skips = result.skip_reasons['reason']
2182
self.assertEqual(1, len(skips))
2184
# RemotedTestCase doesn't preserve the "details"
2185
## self.assertFalse('log' in test.getDetails())
2187
def test_missing_feature_has_no_log(self):
2188
content, result = self.run_subunit_stream('test_missing_feature')
2189
self.assertNotContainsRe(content, '(?m)^log$')
2190
self.assertNotContainsRe(content, 'missing the feature')
2191
self.assertEqual(['_MissingFeature\n'], result.skip_reasons.keys())
2192
skips = result.skip_reasons['_MissingFeature\n']
2193
self.assertEqual(1, len(skips))
2195
# RemotedTestCase doesn't preserve the "details"
2196
## self.assertFalse('log' in test.getDetails())
2198
def test_xfail_has_no_log(self):
2199
content, result = self.run_subunit_stream('test_xfail')
2200
self.assertNotContainsRe(content, '(?m)^log$')
2201
self.assertNotContainsRe(content, 'test with expected failure')
2202
self.assertEqual(1, len(result.expectedFailures))
2203
result_content = result.expectedFailures[0][1]
2204
self.assertNotContainsRe(result_content, 'Text attachment: log')
2205
self.assertNotContainsRe(result_content, 'test with expected failure')
2207
def test_unexpected_success_has_log(self):
2208
content, result = self.run_subunit_stream('test_unexpected_success')
2209
self.assertContainsRe(content, '(?m)^log$')
2210
self.assertContainsRe(content, 'test with unexpected success')
2211
# GZ 2011-05-18: Old versions of subunit treat unexpected success as a
2212
# success, if a min version check is added remove this
2213
from subunit import TestProtocolClient as _Client
2214
if _Client.addUnexpectedSuccess.im_func is _Client.addSuccess.im_func:
2215
self.expectFailure('subunit treats "unexpectedSuccess"'
2216
' as a plain success',
2217
self.assertEqual, 1, len(result.unexpectedSuccesses))
2218
self.assertEqual(1, len(result.unexpectedSuccesses))
2219
test = result.unexpectedSuccesses[0]
2220
# RemotedTestCase doesn't preserve the "details"
2221
## self.assertTrue('log' in test.getDetails())
2223
def test_success_has_no_log(self):
2224
content, result = self.run_subunit_stream('test_success')
2225
self.assertEqual(1, result.testsRun)
2226
self.assertNotContainsRe(content, '(?m)^log$')
2227
self.assertNotContainsRe(content, 'this test succeeds')
1974
2230
class TestRunBzr(tests.TestCase):
2283
2546
def test_allow_plugins(self):
2284
2547
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2286
2549
command = self._popen_args[0]
2287
2550
self.assertEqual([], command[2:])
2289
2552
def test_set_env(self):
2290
self.failIf('EXISTANT_ENV_VAR' in os.environ)
2553
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2291
2554
# set in the child
2292
2555
def check_environment():
2293
2556
self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR'])
2294
2557
self.check_popen_state = check_environment
2295
2558
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2296
env_changes={'EXISTANT_ENV_VAR':'set variable'})
2559
env_changes={'EXISTANT_ENV_VAR':'set variable'})
2297
2560
# not set in theparent
2298
2561
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2300
2563
def test_run_bzr_subprocess_env_del(self):
2301
2564
"""run_bzr_subprocess can remove environment variables too."""
2302
self.failIf('EXISTANT_ENV_VAR' in os.environ)
2565
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2303
2566
def check_environment():
2304
2567
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2305
2568
os.environ['EXISTANT_ENV_VAR'] = 'set variable'
2306
2569
self.check_popen_state = check_environment
2307
2570
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2308
env_changes={'EXISTANT_ENV_VAR':None})
2571
env_changes={'EXISTANT_ENV_VAR':None})
2309
2572
# Still set in parent
2310
2573
self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR'])
2311
2574
del os.environ['EXISTANT_ENV_VAR']
2313
2576
def test_env_del_missing(self):
2314
self.failIf('NON_EXISTANT_ENV_VAR' in os.environ)
2577
self.assertFalse('NON_EXISTANT_ENV_VAR' in os.environ)
2315
2578
def check_environment():
2316
2579
self.assertFalse('NON_EXISTANT_ENV_VAR' in os.environ)
2317
2580
self.check_popen_state = check_environment
2318
2581
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2319
env_changes={'NON_EXISTANT_ENV_VAR':None})
2582
env_changes={'NON_EXISTANT_ENV_VAR':None})
2321
2584
def test_working_dir(self):
2322
2585
"""Test that we can specify the working dir for the child"""
2960
3223
self.assertEquals('bzrlib.plugins', tpr.resolve_alias('bp'))
3226
class TestThreadLeakDetection(tests.TestCase):
3227
"""Ensure when tests leak threads we detect and report it"""
3229
class LeakRecordingResult(tests.ExtendedTestResult):
3231
tests.ExtendedTestResult.__init__(self, StringIO(), 0, 1)
3233
def _report_thread_leak(self, test, leaks, alive):
3234
self.leaks.append((test, leaks))
3236
def test_testcase_without_addCleanups(self):
3237
"""Check old TestCase instances don't break with leak detection"""
3238
class Test(unittest.TestCase):
3241
result = self.LeakRecordingResult()
3243
result.startTestRun()
3245
result.stopTestRun()
3246
self.assertEqual(result._tests_leaking_threads_count, 0)
3247
self.assertEqual(result.leaks, [])
3249
def test_thread_leak(self):
3250
"""Ensure a thread that outlives the running of a test is reported
3252
Uses a thread that blocks on an event, and is started by the inner
3253
test case. As the thread outlives the inner case's run, it should be
3254
detected as a leak, but the event is then set so that the thread can
3255
be safely joined in cleanup so it's not leaked for real.
3257
event = threading.Event()
3258
thread = threading.Thread(name="Leaker", target=event.wait)
3259
class Test(tests.TestCase):
3260
def test_leak(self):
3262
result = self.LeakRecordingResult()
3263
test = Test("test_leak")
3264
self.addCleanup(thread.join)
3265
self.addCleanup(event.set)
3266
result.startTestRun()
3268
result.stopTestRun()
3269
self.assertEqual(result._tests_leaking_threads_count, 1)
3270
self.assertEqual(result._first_thread_leaker_id, test.id())
3271
self.assertEqual(result.leaks, [(test, set([thread]))])
3272
self.assertContainsString(result.stream.getvalue(), "leaking threads")
3274
def test_multiple_leaks(self):
3275
"""Check multiple leaks are blamed on the test cases at fault
3277
Same concept as the previous test, but has one inner test method that
3278
leaks two threads, and one that doesn't leak at all.
3280
event = threading.Event()
3281
thread_a = threading.Thread(name="LeakerA", target=event.wait)
3282
thread_b = threading.Thread(name="LeakerB", target=event.wait)
3283
thread_c = threading.Thread(name="LeakerC", target=event.wait)
3284
class Test(tests.TestCase):
3285
def test_first_leak(self):
3287
def test_second_no_leak(self):
3289
def test_third_leak(self):
3292
result = self.LeakRecordingResult()
3293
first_test = Test("test_first_leak")
3294
third_test = Test("test_third_leak")
3295
self.addCleanup(thread_a.join)
3296
self.addCleanup(thread_b.join)
3297
self.addCleanup(thread_c.join)
3298
self.addCleanup(event.set)
3299
result.startTestRun()
3301
[first_test, Test("test_second_no_leak"), third_test]
3303
result.stopTestRun()
3304
self.assertEqual(result._tests_leaking_threads_count, 2)
3305
self.assertEqual(result._first_thread_leaker_id, first_test.id())
3306
self.assertEqual(result.leaks, [
3307
(first_test, set([thread_b])),
3308
(third_test, set([thread_a, thread_c]))])
3309
self.assertContainsString(result.stream.getvalue(), "leaking threads")
3312
class TestPostMortemDebugging(tests.TestCase):
3313
"""Check post mortem debugging works when tests fail or error"""
3315
class TracebackRecordingResult(tests.ExtendedTestResult):
3317
tests.ExtendedTestResult.__init__(self, StringIO(), 0, 1)
3318
self.postcode = None
3319
def _post_mortem(self, tb=None):
3320
"""Record the code object at the end of the current traceback"""
3321
tb = tb or sys.exc_info()[2]
3324
while next is not None:
3327
self.postcode = tb.tb_frame.f_code
3328
def report_error(self, test, err):
3330
def report_failure(self, test, err):
3333
def test_location_unittest_error(self):
3334
"""Needs right post mortem traceback with erroring unittest case"""
3335
class Test(unittest.TestCase):
3338
result = self.TracebackRecordingResult()
3340
self.assertEqual(result.postcode, Test.runTest.func_code)
3342
def test_location_unittest_failure(self):
3343
"""Needs right post mortem traceback with failing unittest case"""
3344
class Test(unittest.TestCase):
3346
raise self.failureException
3347
result = self.TracebackRecordingResult()
3349
self.assertEqual(result.postcode, Test.runTest.func_code)
3351
def test_location_bt_error(self):
3352
"""Needs right post mortem traceback with erroring bzrlib.tests case"""
3353
class Test(tests.TestCase):
3354
def test_error(self):
3356
result = self.TracebackRecordingResult()
3357
Test("test_error").run(result)
3358
self.assertEqual(result.postcode, Test.test_error.func_code)
3360
def test_location_bt_failure(self):
3361
"""Needs right post mortem traceback with failing bzrlib.tests case"""
3362
class Test(tests.TestCase):
3363
def test_failure(self):
3364
raise self.failureException
3365
result = self.TracebackRecordingResult()
3366
Test("test_failure").run(result)
3367
self.assertEqual(result.postcode, Test.test_failure.func_code)
3369
def test_env_var_triggers_post_mortem(self):
3370
"""Check pdb.post_mortem is called iff BZR_TEST_PDB is set"""
3372
result = tests.ExtendedTestResult(StringIO(), 0, 1)
3373
post_mortem_calls = []
3374
self.overrideAttr(pdb, "post_mortem", post_mortem_calls.append)
3375
self.overrideEnv('BZR_TEST_PDB', None)
3376
result._post_mortem(1)
3377
self.overrideEnv('BZR_TEST_PDB', 'on')
3378
result._post_mortem(2)
3379
self.assertEqual([2], post_mortem_calls)
2963
3382
class TestRunSuite(tests.TestCase):
2965
3384
def test_runner_class(self):
2976
3395
self.verbosity)
2977
3396
tests.run_suite(suite, runner_class=MyRunner, stream=StringIO())
2978
3397
self.assertLength(1, calls)
3400
class TestEnvironHandling(tests.TestCase):
3402
def test_overrideEnv_None_called_twice_doesnt_leak(self):
3403
self.assertFalse('MYVAR' in os.environ)
3404
self.overrideEnv('MYVAR', '42')
3405
# We use an embedded test to make sure we fix the _captureVar bug
3406
class Test(tests.TestCase):
3408
# The first call save the 42 value
3409
self.overrideEnv('MYVAR', None)
3410
self.assertEquals(None, os.environ.get('MYVAR'))
3411
# Make sure we can call it twice
3412
self.overrideEnv('MYVAR', None)
3413
self.assertEquals(None, os.environ.get('MYVAR'))
3415
result = tests.TextTestResult(output, 0, 1)
3416
Test('test_me').run(result)
3417
if not result.wasStrictlySuccessful():
3418
self.fail(output.getvalue())
3419
# We get our value back
3420
self.assertEquals('42', os.environ.get('MYVAR'))
3423
class TestIsolatedEnv(tests.TestCase):
3424
"""Test isolating tests from os.environ.
3426
Since we use tests that are already isolated from os.environ a bit of care
3427
should be taken when designing the tests to avoid bootstrap side-effects.
3428
The tests start an already clean os.environ which allow doing valid
3429
assertions about which variables are present or not and design tests around
3433
class ScratchMonkey(tests.TestCase):
3438
def test_basics(self):
3439
# Make sure we know the definition of BZR_HOME: not part of os.environ
3440
# for tests.TestCase.
3441
self.assertTrue('BZR_HOME' in tests.isolated_environ)
3442
self.assertEquals(None, tests.isolated_environ['BZR_HOME'])
3443
# Being part of isolated_environ, BZR_HOME should not appear here
3444
self.assertFalse('BZR_HOME' in os.environ)
3445
# Make sure we know the definition of LINES: part of os.environ for
3447
self.assertTrue('LINES' in tests.isolated_environ)
3448
self.assertEquals('25', tests.isolated_environ['LINES'])
3449
self.assertEquals('25', os.environ['LINES'])
3451
def test_injecting_unknown_variable(self):
3452
# BZR_HOME is known to be absent from os.environ
3453
test = self.ScratchMonkey('test_me')
3454
tests.override_os_environ(test, {'BZR_HOME': 'foo'})
3455
self.assertEquals('foo', os.environ['BZR_HOME'])
3456
tests.restore_os_environ(test)
3457
self.assertFalse('BZR_HOME' in os.environ)
3459
def test_injecting_known_variable(self):
3460
test = self.ScratchMonkey('test_me')
3461
# LINES is known to be present in os.environ
3462
tests.override_os_environ(test, {'LINES': '42'})
3463
self.assertEquals('42', os.environ['LINES'])
3464
tests.restore_os_environ(test)
3465
self.assertEquals('25', os.environ['LINES'])
3467
def test_deleting_variable(self):
3468
test = self.ScratchMonkey('test_me')
3469
# LINES is known to be present in os.environ
3470
tests.override_os_environ(test, {'LINES': None})
3471
self.assertTrue('LINES' not in os.environ)
3472
tests.restore_os_environ(test)
3473
self.assertEquals('25', os.environ['LINES'])
3476
class TestDocTestSuiteIsolation(tests.TestCase):
3477
"""Test that `tests.DocTestSuite` isolates doc tests from os.environ.
3479
Since tests.TestCase alreay provides an isolation from os.environ, we use
3480
the clean environment as a base for testing. To precisely capture the
3481
isolation provided by tests.DocTestSuite, we use doctest.DocTestSuite to
3484
We want to make sure `tests.DocTestSuite` respect `tests.isolated_environ`,
3485
not `os.environ` so each test overrides it to suit its needs.
3489
def get_doctest_suite_for_string(self, klass, string):
3490
class Finder(doctest.DocTestFinder):
3492
def find(*args, **kwargs):
3493
test = doctest.DocTestParser().get_doctest(
3494
string, {}, 'foo', 'foo.py', 0)
3497
suite = klass(test_finder=Finder())
3500
def run_doctest_suite_for_string(self, klass, string):
3501
suite = self.get_doctest_suite_for_string(klass, string)
3503
result = tests.TextTestResult(output, 0, 1)
3505
return result, output
3507
def assertDocTestStringSucceds(self, klass, string):
3508
result, output = self.run_doctest_suite_for_string(klass, string)
3509
if not result.wasStrictlySuccessful():
3510
self.fail(output.getvalue())
3512
def assertDocTestStringFails(self, klass, string):
3513
result, output = self.run_doctest_suite_for_string(klass, string)
3514
if result.wasStrictlySuccessful():
3515
self.fail(output.getvalue())
3517
def test_injected_variable(self):
3518
self.overrideAttr(tests, 'isolated_environ', {'LINES': '42'})
3521
>>> os.environ['LINES']
3524
# doctest.DocTestSuite fails as it sees '25'
3525
self.assertDocTestStringFails(doctest.DocTestSuite, test)
3526
# tests.DocTestSuite sees '42'
3527
self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
3529
def test_deleted_variable(self):
3530
self.overrideAttr(tests, 'isolated_environ', {'LINES': None})
3533
>>> os.environ.get('LINES')
3535
# doctest.DocTestSuite fails as it sees '25'
3536
self.assertDocTestStringFails(doctest.DocTestSuite, test)
3537
# tests.DocTestSuite sees None
3538
self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
3541
class TestSelftestExcludePatterns(tests.TestCase):
3544
super(TestSelftestExcludePatterns, self).setUp()
3545
self.overrideAttr(tests, 'test_suite', self.suite_factory)
3547
def suite_factory(self, keep_only=None, starting_with=None):
3548
"""A test suite factory with only a few tests."""
3549
class Test(tests.TestCase):
3551
# We don't need the full class path
3552
return self._testMethodName
3559
return TestUtil.TestSuite([Test("a"), Test("b"), Test("c")])
3561
def assertTestList(self, expected, *selftest_args):
3562
# We rely on setUp installing the right test suite factory so we can
3563
# test at the command level without loading the whole test suite
3564
out, err = self.run_bzr(('selftest', '--list') + selftest_args)
3565
actual = out.splitlines()
3566
self.assertEquals(expected, actual)
3568
def test_full_list(self):
3569
self.assertTestList(['a', 'b', 'c'])
3571
def test_single_exclude(self):
3572
self.assertTestList(['b', 'c'], '-x', 'a')
3574
def test_mutiple_excludes(self):
3575
self.assertTestList(['c'], '-x', 'a', '-x', 'b')
3578
class TestCounterHooks(tests.TestCase, SelfTestHelper):
3580
_test_needs_features = [features.subunit]
3583
super(TestCounterHooks, self).setUp()
3584
class Test(tests.TestCase):
3587
super(Test, self).setUp()
3588
self.hooks = hooks.Hooks()
3589
self.hooks.add_hook('myhook', 'Foo bar blah', (2,4))
3590
self.install_counter_hook(self.hooks, 'myhook')
3595
def run_hook_once(self):
3596
for hook in self.hooks['myhook']:
3599
self.test_class = Test
3601
def assertHookCalls(self, expected_calls, test_name):
3602
test = self.test_class(test_name)
3603
result = unittest.TestResult()
3605
self.assertTrue(hasattr(test, '_counters'))
3606
self.assertTrue(test._counters.has_key('myhook'))
3607
self.assertEquals(expected_calls, test._counters['myhook'])
3609
def test_no_hook(self):
3610
self.assertHookCalls(0, 'no_hook')
3612
def test_run_hook_once(self):
3613
tt = features.testtools
3614
if tt.module.__version__ < (0, 9, 8):
3615
raise tests.TestSkipped('testtools-0.9.8 required for addDetail')
3616
self.assertHookCalls(1, 'run_hook_once')