~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_selftest.py

  • Committer: Andrew Bennetts
  • Date: 2010-09-24 02:19:53 UTC
  • mto: This revision was merged to the branch mainline in revision 5443.
  • Revision ID: andrew.bennetts@canonical.com-20100924021953-0cg1kjtifuvkbyzp
Fix typo in test method name.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
"""Tests for the test framework."""
18
18
 
19
19
from cStringIO import StringIO
20
 
import doctest
 
20
from doctest import ELLIPSIS
21
21
import os
22
22
import signal
23
23
import sys
26
26
import unittest
27
27
import warnings
28
28
 
29
 
from testtools import (
30
 
    ExtendedToOriginalDecorator,
31
 
    MultiTestResult,
32
 
    )
 
29
from testtools import MultiTestResult
33
30
from testtools.content import Content
34
31
from testtools.content_type import ContentType
35
32
from testtools.matchers import (
71
68
    test_sftp_transport,
72
69
    TestUtil,
73
70
    )
74
 
from bzrlib.trace import note, mutter
 
71
from bzrlib.trace import note
75
72
from bzrlib.transport import memory
76
73
from bzrlib.version import _get_bzr_source_tree
77
74
 
81
78
    return [t.id() for t in tests.iter_suite_tests(test_suite)]
82
79
 
83
80
 
 
81
class SelftestTests(tests.TestCase):
 
82
 
 
83
    def test_import_tests(self):
 
84
        mod = TestUtil._load_module_by_name('bzrlib.tests.test_selftest')
 
85
        self.assertEqual(mod.SelftestTests, SelftestTests)
 
86
 
 
87
    def test_import_test_failure(self):
 
88
        self.assertRaises(ImportError,
 
89
                          TestUtil._load_module_by_name,
 
90
                          'bzrlib.no-name-yet')
 
91
 
 
92
 
84
93
class MetaTestLog(tests.TestCase):
85
94
 
86
95
    def test_logging(self):
92
101
            "text", "plain", {"charset": "utf8"})))
93
102
        self.assertThat(u"".join(log.iter_text()), Equals(self.get_log()))
94
103
        self.assertThat(self.get_log(),
95
 
            DocTestMatches(u"...a test message\n", doctest.ELLIPSIS))
 
104
            DocTestMatches(u"...a test message\n", ELLIPSIS))
96
105
 
97
106
 
98
107
class TestUnicodeFilename(tests.TestCase):
618
627
        result = test.run()
619
628
        total_failures = result.errors + result.failures
620
629
        if self._lock_check_thorough:
621
 
            self.assertEqual(1, len(total_failures))
 
630
            self.assertLength(1, total_failures)
622
631
        else:
623
632
            # When _lock_check_thorough is disabled, then we don't trigger a
624
633
            # failure
625
 
            self.assertEqual(0, len(total_failures))
 
634
            self.assertLength(0, total_failures)
626
635
 
627
636
 
628
637
class TestTestCaseWithTransport(tests.TestCaseWithTransport):
840
849
        self.assertContainsRe(output,
841
850
            r"LSProf output for <type 'unicode'>\(\('world',\), {'errors': 'replace'}\)\n")
842
851
 
843
 
    def test_uses_time_from_testtools(self):
844
 
        """Test case timings in verbose results should use testtools times"""
845
 
        import datetime
846
 
        class TimeAddedVerboseTestResult(tests.VerboseTestResult):
847
 
            def startTest(self, test):
848
 
                self.time(datetime.datetime.utcfromtimestamp(1.145))
849
 
                super(TimeAddedVerboseTestResult, self).startTest(test)
850
 
            def addSuccess(self, test):
851
 
                self.time(datetime.datetime.utcfromtimestamp(51.147))
852
 
                super(TimeAddedVerboseTestResult, self).addSuccess(test)
853
 
            def report_tests_starting(self): pass
854
 
        sio = StringIO()
855
 
        self.get_passing_test().run(TimeAddedVerboseTestResult(sio, 0, 2))
856
 
        self.assertEndsWith(sio.getvalue(), "OK    50002ms\n")
857
 
 
858
852
    def test_known_failure(self):
859
853
        """A KnownFailure being raised should trigger several result actions."""
860
854
        class InstrumentedTestResult(tests.ExtendedTestResult):
1110
1104
    def test_result_decorator(self):
1111
1105
        # decorate results
1112
1106
        calls = []
1113
 
        class LoggingDecorator(ExtendedToOriginalDecorator):
 
1107
        class LoggingDecorator(tests.ForwardingResult):
1114
1108
            def startTest(self, test):
1115
 
                ExtendedToOriginalDecorator.startTest(self, test)
 
1109
                tests.ForwardingResult.startTest(self, test)
1116
1110
                calls.append('start')
1117
1111
        test = unittest.FunctionTestCase(lambda:None)
1118
1112
        stream = StringIO()
1257
1251
    def test_startTestRun(self):
1258
1252
        """run should call result.startTestRun()"""
1259
1253
        calls = []
1260
 
        class LoggingDecorator(ExtendedToOriginalDecorator):
 
1254
        class LoggingDecorator(tests.ForwardingResult):
1261
1255
            def startTestRun(self):
1262
 
                ExtendedToOriginalDecorator.startTestRun(self)
 
1256
                tests.ForwardingResult.startTestRun(self)
1263
1257
                calls.append('startTestRun')
1264
1258
        test = unittest.FunctionTestCase(lambda:None)
1265
1259
        stream = StringIO()
1271
1265
    def test_stopTestRun(self):
1272
1266
        """run should call result.stopTestRun()"""
1273
1267
        calls = []
1274
 
        class LoggingDecorator(ExtendedToOriginalDecorator):
 
1268
        class LoggingDecorator(tests.ForwardingResult):
1275
1269
            def stopTestRun(self):
1276
 
                ExtendedToOriginalDecorator.stopTestRun(self)
 
1270
                tests.ForwardingResult.stopTestRun(self)
1277
1271
                calls.append('stopTestRun')
1278
1272
        test = unittest.FunctionTestCase(lambda:None)
1279
1273
        stream = StringIO()
1282
1276
        result = self.run_test_runner(runner, test)
1283
1277
        self.assertLength(1, calls)
1284
1278
 
1285
 
    def test_unicode_test_output_on_ascii_stream(self):
1286
 
        """Showing results should always succeed even on an ascii console"""
1287
 
        class FailureWithUnicode(tests.TestCase):
1288
 
            def test_log_unicode(self):
1289
 
                self.log(u"\u2606")
1290
 
                self.fail("Now print that log!")
1291
 
        out = StringIO()
1292
 
        self.overrideAttr(osutils, "get_terminal_encoding",
1293
 
            lambda trace=False: "ascii")
1294
 
        result = self.run_test_runner(tests.TextTestRunner(stream=out),
1295
 
            FailureWithUnicode("test_log_unicode"))
1296
 
        self.assertContainsRe(out.getvalue(),
1297
 
            "Text attachment: log\n"
1298
 
            "-+\n"
1299
 
            "\d+\.\d+  \\\\u2606\n"
1300
 
            "-+\n")
1301
 
 
1302
1279
 
1303
1280
class SampleTestCase(tests.TestCase):
1304
1281
 
1713
1690
        self.assertEqual('original', obj.test_attr)
1714
1691
 
1715
1692
 
1716
 
class _MissingFeature(tests.Feature):
1717
 
    def _probe(self):
1718
 
        return False
1719
 
missing_feature = _MissingFeature()
1720
 
 
1721
 
 
1722
 
def _get_test(name):
1723
 
    """Get an instance of a specific example test.
1724
 
 
1725
 
    We protect this in a function so that they don't auto-run in the test
1726
 
    suite.
1727
 
    """
1728
 
 
1729
 
    class ExampleTests(tests.TestCase):
1730
 
 
1731
 
        def test_fail(self):
1732
 
            mutter('this was a failing test')
1733
 
            self.fail('this test will fail')
1734
 
 
1735
 
        def test_error(self):
1736
 
            mutter('this test errored')
1737
 
            raise RuntimeError('gotcha')
1738
 
 
1739
 
        def test_missing_feature(self):
1740
 
            mutter('missing the feature')
1741
 
            self.requireFeature(missing_feature)
1742
 
 
1743
 
        def test_skip(self):
1744
 
            mutter('this test will be skipped')
1745
 
            raise tests.TestSkipped('reason')
1746
 
 
1747
 
        def test_success(self):
1748
 
            mutter('this test succeeds')
1749
 
 
1750
 
        def test_xfail(self):
1751
 
            mutter('test with expected failure')
1752
 
            self.knownFailure('this_fails')
1753
 
 
1754
 
        def test_unexpected_success(self):
1755
 
            mutter('test with unexpected success')
1756
 
            self.expectFailure('should_fail', lambda: None)
1757
 
 
1758
 
    return ExampleTests(name)
1759
 
 
1760
 
 
1761
 
class TestTestCaseLogDetails(tests.TestCase):
1762
 
 
1763
 
    def _run_test(self, test_name):
1764
 
        test = _get_test(test_name)
1765
 
        result = testtools.TestResult()
1766
 
        test.run(result)
1767
 
        return result
1768
 
 
1769
 
    def test_fail_has_log(self):
1770
 
        result = self._run_test('test_fail')
1771
 
        self.assertEqual(1, len(result.failures))
1772
 
        result_content = result.failures[0][1]
1773
 
        self.assertContainsRe(result_content, 'Text attachment: log')
1774
 
        self.assertContainsRe(result_content, 'this was a failing test')
1775
 
 
1776
 
    def test_error_has_log(self):
1777
 
        result = self._run_test('test_error')
1778
 
        self.assertEqual(1, len(result.errors))
1779
 
        result_content = result.errors[0][1]
1780
 
        self.assertContainsRe(result_content, 'Text attachment: log')
1781
 
        self.assertContainsRe(result_content, 'this test errored')
1782
 
 
1783
 
    def test_skip_has_no_log(self):
1784
 
        result = self._run_test('test_skip')
1785
 
        self.assertEqual(['reason'], result.skip_reasons.keys())
1786
 
        skips = result.skip_reasons['reason']
1787
 
        self.assertEqual(1, len(skips))
1788
 
        test = skips[0]
1789
 
        self.assertFalse('log' in test.getDetails())
1790
 
 
1791
 
    def test_missing_feature_has_no_log(self):
1792
 
        # testtools doesn't know about addNotSupported, so it just gets
1793
 
        # considered as a skip
1794
 
        result = self._run_test('test_missing_feature')
1795
 
        self.assertEqual([missing_feature], result.skip_reasons.keys())
1796
 
        skips = result.skip_reasons[missing_feature]
1797
 
        self.assertEqual(1, len(skips))
1798
 
        test = skips[0]
1799
 
        self.assertFalse('log' in test.getDetails())
1800
 
 
1801
 
    def test_xfail_has_no_log(self):
1802
 
        result = self._run_test('test_xfail')
1803
 
        self.assertEqual(1, len(result.expectedFailures))
1804
 
        result_content = result.expectedFailures[0][1]
1805
 
        self.assertNotContainsRe(result_content, 'Text attachment: log')
1806
 
        self.assertNotContainsRe(result_content, 'test with expected failure')
1807
 
 
1808
 
    def test_unexpected_success_has_log(self):
1809
 
        result = self._run_test('test_unexpected_success')
1810
 
        self.assertEqual(1, len(result.unexpectedSuccesses))
1811
 
        # Inconsistency, unexpectedSuccesses is a list of tests,
1812
 
        # expectedFailures is a list of reasons?
1813
 
        test = result.unexpectedSuccesses[0]
1814
 
        details = test.getDetails()
1815
 
        self.assertTrue('log' in details)
1816
 
 
1817
 
 
1818
1693
class TestTestCloning(tests.TestCase):
1819
1694
    """Tests that test cloning of TestCases (as used by multiply_tests)."""
1820
1695
 
2008
1883
                tree.branch.repository.bzrdir.root_transport)
2009
1884
 
2010
1885
 
2011
 
class SelfTestHelper(object):
 
1886
class SelfTestHelper:
2012
1887
 
2013
1888
    def run_selftest(self, **kwargs):
2014
1889
        """Run selftest returning its output."""
2074
1949
            def __call__(test, result):
2075
1950
                test.run(result)
2076
1951
            def run(test, result):
2077
 
                self.assertIsInstance(result, ExtendedToOriginalDecorator)
 
1952
                self.assertIsInstance(result, tests.ForwardingResult)
2078
1953
                calls.append("called")
2079
1954
            def countTestCases(self):
2080
1955
                return 1
2165
2040
            load_list='missing file name', list_only=True)
2166
2041
 
2167
2042
 
2168
 
class TestSubunitLogDetails(tests.TestCase, SelfTestHelper):
2169
 
 
2170
 
    _test_needs_features = [features.subunit]
2171
 
 
2172
 
    def run_subunit_stream(self, test_name):
2173
 
        from subunit import ProtocolTestCase
2174
 
        def factory():
2175
 
            return TestUtil.TestSuite([_get_test(test_name)])
2176
 
        stream = self.run_selftest(runner_class=tests.SubUnitBzrRunner,
2177
 
            test_suite_factory=factory)
2178
 
        test = ProtocolTestCase(stream)
2179
 
        result = testtools.TestResult()
2180
 
        test.run(result)
2181
 
        content = stream.getvalue()
2182
 
        return content, result
2183
 
 
2184
 
    def test_fail_has_log(self):
2185
 
        content, result = self.run_subunit_stream('test_fail')
2186
 
        self.assertEqual(1, len(result.failures))
2187
 
        self.assertContainsRe(content, '(?m)^log$')
2188
 
        self.assertContainsRe(content, 'this test will fail')
2189
 
 
2190
 
    def test_error_has_log(self):
2191
 
        content, result = self.run_subunit_stream('test_error')
2192
 
        self.assertContainsRe(content, '(?m)^log$')
2193
 
        self.assertContainsRe(content, 'this test errored')
2194
 
 
2195
 
    def test_skip_has_no_log(self):
2196
 
        content, result = self.run_subunit_stream('test_skip')
2197
 
        self.assertNotContainsRe(content, '(?m)^log$')
2198
 
        self.assertNotContainsRe(content, 'this test will be skipped')
2199
 
        self.assertEqual(['reason'], result.skip_reasons.keys())
2200
 
        skips = result.skip_reasons['reason']
2201
 
        self.assertEqual(1, len(skips))
2202
 
        test = skips[0]
2203
 
        # RemotedTestCase doesn't preserve the "details"
2204
 
        ## self.assertFalse('log' in test.getDetails())
2205
 
 
2206
 
    def test_missing_feature_has_no_log(self):
2207
 
        content, result = self.run_subunit_stream('test_missing_feature')
2208
 
        self.assertNotContainsRe(content, '(?m)^log$')
2209
 
        self.assertNotContainsRe(content, 'missing the feature')
2210
 
        self.assertEqual(['_MissingFeature\n'], result.skip_reasons.keys())
2211
 
        skips = result.skip_reasons['_MissingFeature\n']
2212
 
        self.assertEqual(1, len(skips))
2213
 
        test = skips[0]
2214
 
        # RemotedTestCase doesn't preserve the "details"
2215
 
        ## self.assertFalse('log' in test.getDetails())
2216
 
 
2217
 
    def test_xfail_has_no_log(self):
2218
 
        content, result = self.run_subunit_stream('test_xfail')
2219
 
        self.assertNotContainsRe(content, '(?m)^log$')
2220
 
        self.assertNotContainsRe(content, 'test with expected failure')
2221
 
        self.assertEqual(1, len(result.expectedFailures))
2222
 
        result_content = result.expectedFailures[0][1]
2223
 
        self.assertNotContainsRe(result_content, 'Text attachment: log')
2224
 
        self.assertNotContainsRe(result_content, 'test with expected failure')
2225
 
 
2226
 
    def test_unexpected_success_has_log(self):
2227
 
        content, result = self.run_subunit_stream('test_unexpected_success')
2228
 
        self.assertContainsRe(content, '(?m)^log$')
2229
 
        self.assertContainsRe(content, 'test with unexpected success')
2230
 
        self.expectFailure('subunit treats "unexpectedSuccess"'
2231
 
                           ' as a plain success',
2232
 
            self.assertEqual, 1, len(result.unexpectedSuccesses))
2233
 
        self.assertEqual(1, len(result.unexpectedSuccesses))
2234
 
        test = result.unexpectedSuccesses[0]
2235
 
        # RemotedTestCase doesn't preserve the "details"
2236
 
        ## self.assertTrue('log' in test.getDetails())
2237
 
 
2238
 
    def test_success_has_no_log(self):
2239
 
        content, result = self.run_subunit_stream('test_success')
2240
 
        self.assertEqual(1, result.testsRun)
2241
 
        self.assertNotContainsRe(content, '(?m)^log$')
2242
 
        self.assertNotContainsRe(content, 'this test succeeds')
2243
 
 
2244
 
 
2245
2043
class TestRunBzr(tests.TestCase):
2246
2044
 
2247
2045
    out = ''
3210
3008
        tpr.register('bar', 'bBB.aAA.rRR')
3211
3009
        self.assertEquals('bbb.aaa.rrr', tpr.get('bar'))
3212
3010
        self.assertThat(self.get_log(),
3213
 
            DocTestMatches("...bar...bbb.aaa.rrr...BB.aAA.rRR",
3214
 
                           doctest.ELLIPSIS))
 
3011
            DocTestMatches("...bar...bbb.aaa.rrr...BB.aAA.rRR", ELLIPSIS))
3215
3012
 
3216
3013
    def test_get_unknown_prefix(self):
3217
3014
        tpr = self._get_registry()
3252
3049
        class Test(unittest.TestCase):
3253
3050
            def runTest(self):
3254
3051
                pass
 
3052
            addCleanup = None # for when on Python 2.7 with native addCleanup
3255
3053
        result = self.LeakRecordingResult()
3256
3054
        test = Test()
 
3055
        self.assertIs(getattr(test, "addCleanup", None), None)
3257
3056
        result.startTestRun()
3258
3057
        test.run(result)
3259
3058
        result.stopTestRun()
3323
3122
        self.assertContainsString(result.stream.getvalue(), "leaking threads")
3324
3123
 
3325
3124
 
3326
 
class TestPostMortemDebugging(tests.TestCase):
3327
 
    """Check post mortem debugging works when tests fail or error"""
3328
 
 
3329
 
    class TracebackRecordingResult(tests.ExtendedTestResult):
3330
 
        def __init__(self):
3331
 
            tests.ExtendedTestResult.__init__(self, StringIO(), 0, 1)
3332
 
            self.postcode = None
3333
 
        def _post_mortem(self, tb=None):
3334
 
            """Record the code object at the end of the current traceback"""
3335
 
            tb = tb or sys.exc_info()[2]
3336
 
            if tb is not None:
3337
 
                next = tb.tb_next
3338
 
                while next is not None:
3339
 
                    tb = next
3340
 
                    next = next.tb_next
3341
 
                self.postcode = tb.tb_frame.f_code
3342
 
        def report_error(self, test, err):
3343
 
            pass
3344
 
        def report_failure(self, test, err):
3345
 
            pass
3346
 
 
3347
 
    def test_location_unittest_error(self):
3348
 
        """Needs right post mortem traceback with erroring unittest case"""
3349
 
        class Test(unittest.TestCase):
3350
 
            def runTest(self):
3351
 
                raise RuntimeError
3352
 
        result = self.TracebackRecordingResult()
3353
 
        Test().run(result)
3354
 
        self.assertEqual(result.postcode, Test.runTest.func_code)
3355
 
 
3356
 
    def test_location_unittest_failure(self):
3357
 
        """Needs right post mortem traceback with failing unittest case"""
3358
 
        class Test(unittest.TestCase):
3359
 
            def runTest(self):
3360
 
                raise self.failureException
3361
 
        result = self.TracebackRecordingResult()
3362
 
        Test().run(result)
3363
 
        self.assertEqual(result.postcode, Test.runTest.func_code)
3364
 
 
3365
 
    def test_location_bt_error(self):
3366
 
        """Needs right post mortem traceback with erroring bzrlib.tests case"""
3367
 
        class Test(tests.TestCase):
3368
 
            def test_error(self):
3369
 
                raise RuntimeError
3370
 
        result = self.TracebackRecordingResult()
3371
 
        Test("test_error").run(result)
3372
 
        self.assertEqual(result.postcode, Test.test_error.func_code)
3373
 
 
3374
 
    def test_location_bt_failure(self):
3375
 
        """Needs right post mortem traceback with failing bzrlib.tests case"""
3376
 
        class Test(tests.TestCase):
3377
 
            def test_failure(self):
3378
 
                raise self.failureException
3379
 
        result = self.TracebackRecordingResult()
3380
 
        Test("test_failure").run(result)
3381
 
        self.assertEqual(result.postcode, Test.test_failure.func_code)
3382
 
 
3383
 
    def test_env_var_triggers_post_mortem(self):
3384
 
        """Check pdb.post_mortem is called iff BZR_TEST_PDB is set"""
3385
 
        import pdb
3386
 
        result = tests.ExtendedTestResult(StringIO(), 0, 1)
3387
 
        post_mortem_calls = []
3388
 
        self.overrideAttr(pdb, "post_mortem", post_mortem_calls.append)
3389
 
        self.overrideEnv('BZR_TEST_PDB', None)
3390
 
        result._post_mortem(1)
3391
 
        self.overrideEnv('BZR_TEST_PDB', 'on')
3392
 
        result._post_mortem(2)
3393
 
        self.assertEqual([2], post_mortem_calls)
3394
 
 
3395
 
 
3396
3125
class TestRunSuite(tests.TestCase):
3397
3126
 
3398
3127
    def test_runner_class(self):
3409
3138
                                                self.verbosity)
3410
3139
        tests.run_suite(suite, runner_class=MyRunner, stream=StringIO())
3411
3140
        self.assertLength(1, calls)
3412
 
 
3413
 
 
3414
 
class TestEnvironHandling(tests.TestCase):
3415
 
 
3416
 
    def test_overrideEnv_None_called_twice_doesnt_leak(self):
3417
 
        self.failIf('MYVAR' in os.environ)
3418
 
        self.overrideEnv('MYVAR', '42')
3419
 
        # We use an embedded test to make sure we fix the _captureVar bug
3420
 
        class Test(tests.TestCase):
3421
 
            def test_me(self):
3422
 
                # The first call save the 42 value
3423
 
                self.overrideEnv('MYVAR', None)
3424
 
                self.assertEquals(None, os.environ.get('MYVAR'))
3425
 
                # Make sure we can call it twice
3426
 
                self.overrideEnv('MYVAR', None)
3427
 
                self.assertEquals(None, os.environ.get('MYVAR'))
3428
 
        output = StringIO()
3429
 
        result = tests.TextTestResult(output, 0, 1)
3430
 
        Test('test_me').run(result)
3431
 
        if not result.wasStrictlySuccessful():
3432
 
            self.fail(output.getvalue())
3433
 
        # We get our value back
3434
 
        self.assertEquals('42', os.environ.get('MYVAR'))
3435
 
 
3436
 
 
3437
 
class TestIsolatedEnv(tests.TestCase):
3438
 
    """Test isolating tests from os.environ.
3439
 
 
3440
 
    Since we use tests that are already isolated from os.environ a bit of care
3441
 
    should be taken when designing the tests to avoid bootstrap side-effects.
3442
 
    The tests start an already clean os.environ which allow doing valid
3443
 
    assertions about which variables are present or not and design tests around
3444
 
    these assertions.
3445
 
    """
3446
 
 
3447
 
    class ScratchMonkey(tests.TestCase):
3448
 
 
3449
 
        def test_me(self):
3450
 
            pass
3451
 
 
3452
 
    def test_basics(self):
3453
 
        # Make sure we know the definition of BZR_HOME: not part of os.environ
3454
 
        # for tests.TestCase.
3455
 
        self.assertTrue('BZR_HOME' in tests.isolated_environ)
3456
 
        self.assertEquals(None, tests.isolated_environ['BZR_HOME'])
3457
 
        # Being part of isolated_environ, BZR_HOME should not appear here
3458
 
        self.assertFalse('BZR_HOME' in os.environ)
3459
 
        # Make sure we know the definition of LINES: part of os.environ for
3460
 
        # tests.TestCase
3461
 
        self.assertTrue('LINES' in tests.isolated_environ)
3462
 
        self.assertEquals('25', tests.isolated_environ['LINES'])
3463
 
        self.assertEquals('25', os.environ['LINES'])
3464
 
 
3465
 
    def test_injecting_unknown_variable(self):
3466
 
        # BZR_HOME is known to be absent from os.environ
3467
 
        test = self.ScratchMonkey('test_me')
3468
 
        tests.override_os_environ(test, {'BZR_HOME': 'foo'})
3469
 
        self.assertEquals('foo', os.environ['BZR_HOME'])
3470
 
        tests.restore_os_environ(test)
3471
 
        self.assertFalse('BZR_HOME' in os.environ)
3472
 
 
3473
 
    def test_injecting_known_variable(self):
3474
 
        test = self.ScratchMonkey('test_me')
3475
 
        # LINES is known to be present in os.environ
3476
 
        tests.override_os_environ(test, {'LINES': '42'})
3477
 
        self.assertEquals('42', os.environ['LINES'])
3478
 
        tests.restore_os_environ(test)
3479
 
        self.assertEquals('25', os.environ['LINES'])
3480
 
 
3481
 
    def test_deleting_variable(self):
3482
 
        test = self.ScratchMonkey('test_me')
3483
 
        # LINES is known to be present in os.environ
3484
 
        tests.override_os_environ(test, {'LINES': None})
3485
 
        self.assertTrue('LINES' not in os.environ)
3486
 
        tests.restore_os_environ(test)
3487
 
        self.assertEquals('25', os.environ['LINES'])
3488
 
 
3489
 
 
3490
 
class TestDocTestSuiteIsolation(tests.TestCase):
3491
 
    """Test that `tests.DocTestSuite` isolates doc tests from os.environ.
3492
 
 
3493
 
    Since tests.TestCase alreay provides an isolation from os.environ, we use
3494
 
    the clean environment as a base for testing. To precisely capture the
3495
 
    isolation provided by tests.DocTestSuite, we use doctest.DocTestSuite to
3496
 
    compare against.
3497
 
 
3498
 
    We want to make sure `tests.DocTestSuite` respect `tests.isolated_environ`,
3499
 
    not `os.environ` so each test overrides it to suit its needs.
3500
 
 
3501
 
    """
3502
 
 
3503
 
    def get_doctest_suite_for_string(self, klass, string):
3504
 
        class Finder(doctest.DocTestFinder):
3505
 
 
3506
 
            def find(*args, **kwargs):
3507
 
                test = doctest.DocTestParser().get_doctest(
3508
 
                    string, {}, 'foo', 'foo.py', 0)
3509
 
                return [test]
3510
 
 
3511
 
        suite = klass(test_finder=Finder())
3512
 
        return suite
3513
 
 
3514
 
    def run_doctest_suite_for_string(self, klass, string):
3515
 
        suite = self.get_doctest_suite_for_string(klass, string)
3516
 
        output = StringIO()
3517
 
        result = tests.TextTestResult(output, 0, 1)
3518
 
        suite.run(result)
3519
 
        return result, output
3520
 
 
3521
 
    def assertDocTestStringSucceds(self, klass, string):
3522
 
        result, output = self.run_doctest_suite_for_string(klass, string)
3523
 
        if not result.wasStrictlySuccessful():
3524
 
            self.fail(output.getvalue())
3525
 
 
3526
 
    def assertDocTestStringFails(self, klass, string):
3527
 
        result, output = self.run_doctest_suite_for_string(klass, string)
3528
 
        if result.wasStrictlySuccessful():
3529
 
            self.fail(output.getvalue())
3530
 
 
3531
 
    def test_injected_variable(self):
3532
 
        self.overrideAttr(tests, 'isolated_environ', {'LINES': '42'})
3533
 
        test = """
3534
 
            >>> import os
3535
 
            >>> os.environ['LINES']
3536
 
            '42'
3537
 
            """
3538
 
        # doctest.DocTestSuite fails as it sees '25'
3539
 
        self.assertDocTestStringFails(doctest.DocTestSuite, test)
3540
 
        # tests.DocTestSuite sees '42'
3541
 
        self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
3542
 
 
3543
 
    def test_deleted_variable(self):
3544
 
        self.overrideAttr(tests, 'isolated_environ', {'LINES': None})
3545
 
        test = """
3546
 
            >>> import os
3547
 
            >>> os.environ.get('LINES')
3548
 
            """
3549
 
        # doctest.DocTestSuite fails as it sees '25'
3550
 
        self.assertDocTestStringFails(doctest.DocTestSuite, test)
3551
 
        # tests.DocTestSuite sees None
3552
 
        self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)