1198
def test_verbose_test_count(self):
1199
"""A verbose test run reports the right test count at the start"""
1200
suite = TestUtil.TestSuite([
1201
unittest.FunctionTestCase(lambda:None),
1202
unittest.FunctionTestCase(lambda:None)])
1203
self.assertEqual(suite.countTestCases(), 2)
1205
runner = tests.TextTestRunner(stream=stream, verbosity=2)
1206
# Need to use the CountingDecorator as that's what sets num_tests
1207
result = self.run_test_runner(runner, tests.CountingDecorator(suite))
1208
self.assertStartsWith(stream.getvalue(), "running 2 tests")
1210
def test_startTestRun(self):
1211
"""run should call result.startTestRun()"""
1213
class LoggingDecorator(ExtendedToOriginalDecorator):
1214
def startTestRun(self):
1215
ExtendedToOriginalDecorator.startTestRun(self)
1216
calls.append('startTestRun')
1217
test = unittest.FunctionTestCase(lambda:None)
1219
runner = tests.TextTestRunner(stream=stream,
1220
result_decorators=[LoggingDecorator])
1221
result = self.run_test_runner(runner, test)
1222
self.assertLength(1, calls)
1224
def test_stopTestRun(self):
1225
"""run should call result.stopTestRun()"""
1227
class LoggingDecorator(ExtendedToOriginalDecorator):
1228
def stopTestRun(self):
1229
ExtendedToOriginalDecorator.stopTestRun(self)
1230
calls.append('stopTestRun')
1231
test = unittest.FunctionTestCase(lambda:None)
1233
runner = tests.TextTestRunner(stream=stream,
1234
result_decorators=[LoggingDecorator])
1235
result = self.run_test_runner(runner, test)
1236
self.assertLength(1, calls)
1238
def test_unicode_test_output_on_ascii_stream(self):
1239
"""Showing results should always succeed even on an ascii console"""
1240
class FailureWithUnicode(tests.TestCase):
1241
def test_log_unicode(self):
1243
self.fail("Now print that log!")
1245
self.overrideAttr(osutils, "get_terminal_encoding",
1246
lambda trace=False: "ascii")
1247
result = self.run_test_runner(tests.TextTestRunner(stream=out),
1248
FailureWithUnicode("test_log_unicode"))
1249
self.assertContainsRe(out.getvalue(),
1250
"Text attachment: log\n"
1252
"\d+\.\d+ \\\\u2606\n"
1256
class SampleTestCase(tests.TestCase):
1246
def test_bench_history(self):
1247
# tests that the running the benchmark produces a history file
1248
# containing a timestamp and the revision id of the bzrlib source which
1250
workingtree = _get_bzr_source_tree()
1251
test = TestRunner('dummy_test')
1253
runner = TextTestRunner(stream=self._log_file, bench_history=output)
1254
result = self.run_test_runner(runner, test)
1255
output_string = output.getvalue()
1256
self.assertContainsRe(output_string, "--date [0-9.]+")
1257
if workingtree is not None:
1258
revision_id = workingtree.get_parent_ids()[0]
1259
self.assertEndsWith(output_string.rstrip(), revision_id)
1261
def assertLogDeleted(self, test):
1262
log = test._get_log()
1263
self.assertEqual("DELETED log file to reduce memory footprint", log)
1264
self.assertEqual('', test._log_contents)
1265
self.assertIs(None, test._log_file_name)
1267
def test_success_log_deleted(self):
1268
"""Successful tests have their log deleted"""
1270
class LogTester(TestCase):
1272
def test_success(self):
1273
self.log('this will be removed\n')
1275
sio = cStringIO.StringIO()
1276
runner = TextTestRunner(stream=sio)
1277
test = LogTester('test_success')
1278
result = self.run_test_runner(runner, test)
1280
self.assertLogDeleted(test)
1282
def test_skipped_log_deleted(self):
1283
"""Skipped tests have their log deleted"""
1285
class LogTester(TestCase):
1287
def test_skipped(self):
1288
self.log('this will be removed\n')
1289
raise tests.TestSkipped()
1291
sio = cStringIO.StringIO()
1292
runner = TextTestRunner(stream=sio)
1293
test = LogTester('test_skipped')
1294
result = self.run_test_runner(runner, test)
1296
self.assertLogDeleted(test)
1298
def test_not_aplicable_log_deleted(self):
1299
"""Not applicable tests have their log deleted"""
1301
class LogTester(TestCase):
1303
def test_not_applicable(self):
1304
self.log('this will be removed\n')
1305
raise tests.TestNotApplicable()
1307
sio = cStringIO.StringIO()
1308
runner = TextTestRunner(stream=sio)
1309
test = LogTester('test_not_applicable')
1310
result = self.run_test_runner(runner, test)
1312
self.assertLogDeleted(test)
1314
def test_known_failure_log_deleted(self):
1315
"""Know failure tests have their log deleted"""
1317
class LogTester(TestCase):
1319
def test_known_failure(self):
1320
self.log('this will be removed\n')
1321
raise tests.KnownFailure()
1323
sio = cStringIO.StringIO()
1324
runner = TextTestRunner(stream=sio)
1325
test = LogTester('test_known_failure')
1326
result = self.run_test_runner(runner, test)
1328
self.assertLogDeleted(test)
1330
def test_fail_log_kept(self):
1331
"""Failed tests have their log kept"""
1333
class LogTester(TestCase):
1335
def test_fail(self):
1336
self.log('this will be kept\n')
1337
self.fail('this test fails')
1339
sio = cStringIO.StringIO()
1340
runner = TextTestRunner(stream=sio)
1341
test = LogTester('test_fail')
1342
result = self.run_test_runner(runner, test)
1344
text = sio.getvalue()
1345
self.assertContainsRe(text, 'this will be kept')
1346
self.assertContainsRe(text, 'this test fails')
1348
log = test._get_log()
1349
self.assertContainsRe(log, 'this will be kept')
1350
self.assertEqual(log, test._log_contents)
1352
def test_error_log_kept(self):
1353
"""Tests with errors have their log kept"""
1355
class LogTester(TestCase):
1357
def test_error(self):
1358
self.log('this will be kept\n')
1359
raise ValueError('random exception raised')
1361
sio = cStringIO.StringIO()
1362
runner = TextTestRunner(stream=sio)
1363
test = LogTester('test_error')
1364
result = self.run_test_runner(runner, test)
1366
text = sio.getvalue()
1367
self.assertContainsRe(text, 'this will be kept')
1368
self.assertContainsRe(text, 'random exception raised')
1370
log = test._get_log()
1371
self.assertContainsRe(log, 'this will be kept')
1372
self.assertEqual(log, test._log_contents)
1375
class SampleTestCase(TestCase):
1258
1377
def _test_pass(self):
1629
1683
self.assertRaises(AssertionError,
1630
1684
self.assertListRaises, _TestException, success_generator)
1632
def test_overrideAttr_without_value(self):
1633
self.test_attr = 'original' # Define a test attribute
1634
obj = self # Make 'obj' visible to the embedded test
1635
class Test(tests.TestCase):
1638
tests.TestCase.setUp(self)
1639
self.orig = self.overrideAttr(obj, 'test_attr')
1641
def test_value(self):
1642
self.assertEqual('original', self.orig)
1643
self.assertEqual('original', obj.test_attr)
1644
obj.test_attr = 'modified'
1645
self.assertEqual('modified', obj.test_attr)
1647
test = Test('test_value')
1648
test.run(unittest.TestResult())
1649
self.assertEqual('original', obj.test_attr)
1651
def test_overrideAttr_with_value(self):
1652
self.test_attr = 'original' # Define a test attribute
1653
obj = self # Make 'obj' visible to the embedded test
1654
class Test(tests.TestCase):
1657
tests.TestCase.setUp(self)
1658
self.orig = self.overrideAttr(obj, 'test_attr', new='modified')
1660
def test_value(self):
1661
self.assertEqual('original', self.orig)
1662
self.assertEqual('modified', obj.test_attr)
1664
test = Test('test_value')
1665
test.run(unittest.TestResult())
1666
self.assertEqual('original', obj.test_attr)
1669
class _MissingFeature(tests.Feature):
1672
missing_feature = _MissingFeature()
1675
def _get_test(name):
1676
"""Get an instance of a specific example test.
1678
We protect this in a function so that they don't auto-run in the test
1682
class ExampleTests(tests.TestCase):
1684
def test_fail(self):
1685
mutter('this was a failing test')
1686
self.fail('this test will fail')
1688
def test_error(self):
1689
mutter('this test errored')
1690
raise RuntimeError('gotcha')
1692
def test_missing_feature(self):
1693
mutter('missing the feature')
1694
self.requireFeature(missing_feature)
1696
def test_skip(self):
1697
mutter('this test will be skipped')
1698
raise tests.TestSkipped('reason')
1700
def test_success(self):
1701
mutter('this test succeeds')
1703
def test_xfail(self):
1704
mutter('test with expected failure')
1705
self.knownFailure('this_fails')
1707
def test_unexpected_success(self):
1708
mutter('test with unexpected success')
1709
self.expectFailure('should_fail', lambda: None)
1711
return ExampleTests(name)
1714
class TestTestCaseLogDetails(tests.TestCase):
1716
def _run_test(self, test_name):
1717
test = _get_test(test_name)
1718
result = testtools.TestResult()
1722
def test_fail_has_log(self):
1723
result = self._run_test('test_fail')
1724
self.assertEqual(1, len(result.failures))
1725
result_content = result.failures[0][1]
1726
self.assertContainsRe(result_content, 'Text attachment: log')
1727
self.assertContainsRe(result_content, 'this was a failing test')
1729
def test_error_has_log(self):
1730
result = self._run_test('test_error')
1731
self.assertEqual(1, len(result.errors))
1732
result_content = result.errors[0][1]
1733
self.assertContainsRe(result_content, 'Text attachment: log')
1734
self.assertContainsRe(result_content, 'this test errored')
1736
def test_skip_has_no_log(self):
1737
result = self._run_test('test_skip')
1738
self.assertEqual(['reason'], result.skip_reasons.keys())
1739
skips = result.skip_reasons['reason']
1740
self.assertEqual(1, len(skips))
1742
self.assertFalse('log' in test.getDetails())
1744
def test_missing_feature_has_no_log(self):
1745
# testtools doesn't know about addNotSupported, so it just gets
1746
# considered as a skip
1747
result = self._run_test('test_missing_feature')
1748
self.assertEqual([missing_feature], result.skip_reasons.keys())
1749
skips = result.skip_reasons[missing_feature]
1750
self.assertEqual(1, len(skips))
1752
self.assertFalse('log' in test.getDetails())
1754
def test_xfail_has_no_log(self):
1755
result = self._run_test('test_xfail')
1756
self.assertEqual(1, len(result.expectedFailures))
1757
result_content = result.expectedFailures[0][1]
1758
self.assertNotContainsRe(result_content, 'Text attachment: log')
1759
self.assertNotContainsRe(result_content, 'test with expected failure')
1761
def test_unexpected_success_has_log(self):
1762
result = self._run_test('test_unexpected_success')
1763
self.assertEqual(1, len(result.unexpectedSuccesses))
1764
# Inconsistency, unexpectedSuccesses is a list of tests,
1765
# expectedFailures is a list of reasons?
1766
test = result.unexpectedSuccesses[0]
1767
details = test.getDetails()
1768
self.assertTrue('log' in details)
1771
class TestTestCloning(tests.TestCase):
1772
"""Tests that test cloning of TestCases (as used by multiply_tests)."""
1774
def test_cloned_testcase_does_not_share_details(self):
1775
"""A TestCase cloned with clone_test does not share mutable attributes
1776
such as details or cleanups.
1778
class Test(tests.TestCase):
1780
self.addDetail('foo', Content('text/plain', lambda: 'foo'))
1781
orig_test = Test('test_foo')
1782
cloned_test = tests.clone_test(orig_test, orig_test.id() + '(cloned)')
1783
orig_test.run(unittest.TestResult())
1784
self.assertEqual('foo', orig_test.getDetails()['foo'].iter_bytes())
1785
self.assertEqual(None, cloned_test.getDetails().get('foo'))
1787
def test_double_apply_scenario_preserves_first_scenario(self):
1788
"""Applying two levels of scenarios to a test preserves the attributes
1789
added by both scenarios.
1791
class Test(tests.TestCase):
1794
test = Test('test_foo')
1795
scenarios_x = [('x=1', {'x': 1}), ('x=2', {'x': 2})]
1796
scenarios_y = [('y=1', {'y': 1}), ('y=2', {'y': 2})]
1797
suite = tests.multiply_tests(test, scenarios_x, unittest.TestSuite())
1798
suite = tests.multiply_tests(suite, scenarios_y, unittest.TestSuite())
1799
all_tests = list(tests.iter_suite_tests(suite))
1800
self.assertLength(4, all_tests)
1801
all_xys = sorted((t.x, t.y) for t in all_tests)
1802
self.assertEqual([(1, 1), (1, 2), (2, 1), (2, 2)], all_xys)
1805
1687
# NB: Don't delete this; it's not actually from 0.11!
1806
1688
@deprecated_function(deprecated_in((0, 11, 0)))
1943
1806
tree = self.make_branch_and_memory_tree('a')
1944
1807
self.assertIsInstance(tree, bzrlib.memorytree.MemoryTree)
1946
def test_make_tree_for_local_vfs_backed_transport(self):
1947
# make_branch_and_tree has to use local branch and repositories
1948
# when the vfs transport and local disk are colocated, even if
1949
# a different transport is in use for url generation.
1950
self.transport_server = test_server.FakeVFATServer
1951
self.assertFalse(self.get_url('t1').startswith('file://'))
1810
class TestSFTPMakeBranchAndTree(TestCaseWithSFTPServer):
1812
def test_make_tree_for_sftp_branch(self):
1813
"""Transports backed by local directories create local trees."""
1952
1815
tree = self.make_branch_and_tree('t1')
1953
1816
base = tree.bzrdir.root_transport.base
1954
self.assertStartsWith(base, 'file://')
1817
self.failIf(base.startswith('sftp'),
1818
'base %r is on sftp but should be local' % base)
1955
1819
self.assertEquals(tree.bzrdir.root_transport,
1956
1820
tree.branch.bzrdir.root_transport)
1957
1821
self.assertEquals(tree.bzrdir.root_transport,
1958
1822
tree.branch.repository.bzrdir.root_transport)
1961
class SelfTestHelper(object):
1963
def run_selftest(self, **kwargs):
1964
"""Run selftest returning its output."""
1966
old_transport = bzrlib.tests.default_transport
1967
old_root = tests.TestCaseWithMemoryTransport.TEST_ROOT
1968
tests.TestCaseWithMemoryTransport.TEST_ROOT = None
1970
self.assertEqual(True, tests.selftest(stream=output, **kwargs))
1972
bzrlib.tests.default_transport = old_transport
1973
tests.TestCaseWithMemoryTransport.TEST_ROOT = old_root
1978
class TestSelftest(tests.TestCase, SelfTestHelper):
1825
class TestSelftest(TestCase):
1979
1826
"""Tests of bzrlib.tests.selftest."""
1981
1828
def test_selftest_benchmark_parameter_invokes_test_suite__benchmark__(self):
1982
1829
factory_called = []
1984
1831
factory_called.append(True)
1985
return TestUtil.TestSuite()
1986
1833
out = StringIO()
1987
1834
err = StringIO()
1988
1835
self.apply_redirected(out, err, None, bzrlib.tests.selftest,
1989
1836
test_suite_factory=factory)
1990
1837
self.assertEqual([True], factory_called)
1993
"""A test suite factory."""
1994
class Test(tests.TestCase):
2001
return TestUtil.TestSuite([Test("a"), Test("b"), Test("c")])
2003
def test_list_only(self):
2004
output = self.run_selftest(test_suite_factory=self.factory,
2006
self.assertEqual(3, len(output.readlines()))
2008
def test_list_only_filtered(self):
2009
output = self.run_selftest(test_suite_factory=self.factory,
2010
list_only=True, pattern="Test.b")
2011
self.assertEndsWith(output.getvalue(), "Test.b\n")
2012
self.assertLength(1, output.readlines())
2014
def test_list_only_excludes(self):
2015
output = self.run_selftest(test_suite_factory=self.factory,
2016
list_only=True, exclude_pattern="Test.b")
2017
self.assertNotContainsRe("Test.b", output.getvalue())
2018
self.assertLength(2, output.readlines())
2020
def test_lsprof_tests(self):
2021
self.requireFeature(test_lsprof.LSProfFeature)
2024
def __call__(test, result):
2026
def run(test, result):
2027
self.assertIsInstance(result, ExtendedToOriginalDecorator)
2028
calls.append("called")
2029
def countTestCases(self):
2031
self.run_selftest(test_suite_factory=Test, lsprof_tests=True)
2032
self.assertLength(1, calls)
2034
def test_random(self):
2035
# test randomising by listing a number of tests.
2036
output_123 = self.run_selftest(test_suite_factory=self.factory,
2037
list_only=True, random_seed="123")
2038
output_234 = self.run_selftest(test_suite_factory=self.factory,
2039
list_only=True, random_seed="234")
2040
self.assertNotEqual(output_123, output_234)
2041
# "Randominzing test order..\n\n
2042
self.assertLength(5, output_123.readlines())
2043
self.assertLength(5, output_234.readlines())
2045
def test_random_reuse_is_same_order(self):
2046
# test randomising by listing a number of tests.
2047
expected = self.run_selftest(test_suite_factory=self.factory,
2048
list_only=True, random_seed="123")
2049
repeated = self.run_selftest(test_suite_factory=self.factory,
2050
list_only=True, random_seed="123")
2051
self.assertEqual(expected.getvalue(), repeated.getvalue())
2053
def test_runner_class(self):
2054
self.requireFeature(features.subunit)
2055
from subunit import ProtocolTestCase
2056
stream = self.run_selftest(runner_class=tests.SubUnitBzrRunner,
2057
test_suite_factory=self.factory)
2058
test = ProtocolTestCase(stream)
2059
result = unittest.TestResult()
2061
self.assertEqual(3, result.testsRun)
2063
def test_starting_with_single_argument(self):
2064
output = self.run_selftest(test_suite_factory=self.factory,
2065
starting_with=['bzrlib.tests.test_selftest.Test.a'],
2067
self.assertEqual('bzrlib.tests.test_selftest.Test.a\n',
2070
def test_starting_with_multiple_argument(self):
2071
output = self.run_selftest(test_suite_factory=self.factory,
2072
starting_with=['bzrlib.tests.test_selftest.Test.a',
2073
'bzrlib.tests.test_selftest.Test.b'],
2075
self.assertEqual('bzrlib.tests.test_selftest.Test.a\n'
2076
'bzrlib.tests.test_selftest.Test.b\n',
2079
def check_transport_set(self, transport_server):
2080
captured_transport = []
2081
def seen_transport(a_transport):
2082
captured_transport.append(a_transport)
2083
class Capture(tests.TestCase):
2085
seen_transport(bzrlib.tests.default_transport)
2087
return TestUtil.TestSuite([Capture("a")])
2088
self.run_selftest(transport=transport_server, test_suite_factory=factory)
2089
self.assertEqual(transport_server, captured_transport[0])
2091
def test_transport_sftp(self):
2092
self.requireFeature(features.paramiko)
2093
from bzrlib.tests import stub_sftp
2094
self.check_transport_set(stub_sftp.SFTPAbsoluteServer)
2096
def test_transport_memory(self):
2097
self.check_transport_set(memory.MemoryServer)
2100
class TestSelftestWithIdList(tests.TestCaseInTempDir, SelfTestHelper):
2101
# Does IO: reads test.list
2103
def test_load_list(self):
2104
# Provide a list with one test - this test.
2105
test_id_line = '%s\n' % self.id()
2106
self.build_tree_contents([('test.list', test_id_line)])
2107
# And generate a list of the tests in the suite.
2108
stream = self.run_selftest(load_list='test.list', list_only=True)
2109
self.assertEqual(test_id_line, stream.getvalue())
2111
def test_load_unknown(self):
2112
# Provide a list with one test - this test.
2113
# And generate a list of the tests in the suite.
2114
err = self.assertRaises(errors.NoSuchFile, self.run_selftest,
2115
load_list='missing file name', list_only=True)
2118
class TestSubunitLogDetails(tests.TestCase, SelfTestHelper):
2120
_test_needs_features = [features.subunit]
2122
def run_subunit_stream(self, test_name):
2123
from subunit import ProtocolTestCase
2125
return TestUtil.TestSuite([_get_test(test_name)])
2126
stream = self.run_selftest(runner_class=tests.SubUnitBzrRunner,
2127
test_suite_factory=factory)
2128
test = ProtocolTestCase(stream)
2129
result = testtools.TestResult()
2131
content = stream.getvalue()
2132
return content, result
2134
def test_fail_has_log(self):
2135
content, result = self.run_subunit_stream('test_fail')
2136
self.assertEqual(1, len(result.failures))
2137
self.assertContainsRe(content, '(?m)^log$')
2138
self.assertContainsRe(content, 'this test will fail')
2140
def test_error_has_log(self):
2141
content, result = self.run_subunit_stream('test_error')
2142
self.assertContainsRe(content, '(?m)^log$')
2143
self.assertContainsRe(content, 'this test errored')
2145
def test_skip_has_no_log(self):
2146
content, result = self.run_subunit_stream('test_skip')
2147
self.assertNotContainsRe(content, '(?m)^log$')
2148
self.assertNotContainsRe(content, 'this test will be skipped')
2149
self.assertEqual(['reason'], result.skip_reasons.keys())
2150
skips = result.skip_reasons['reason']
2151
self.assertEqual(1, len(skips))
2153
# RemotedTestCase doesn't preserve the "details"
2154
## self.assertFalse('log' in test.getDetails())
2156
def test_missing_feature_has_no_log(self):
2157
content, result = self.run_subunit_stream('test_missing_feature')
2158
self.assertNotContainsRe(content, '(?m)^log$')
2159
self.assertNotContainsRe(content, 'missing the feature')
2160
self.assertEqual(['_MissingFeature\n'], result.skip_reasons.keys())
2161
skips = result.skip_reasons['_MissingFeature\n']
2162
self.assertEqual(1, len(skips))
2164
# RemotedTestCase doesn't preserve the "details"
2165
## self.assertFalse('log' in test.getDetails())
2167
def test_xfail_has_no_log(self):
2168
content, result = self.run_subunit_stream('test_xfail')
2169
self.assertNotContainsRe(content, '(?m)^log$')
2170
self.assertNotContainsRe(content, 'test with expected failure')
2171
self.assertEqual(1, len(result.expectedFailures))
2172
result_content = result.expectedFailures[0][1]
2173
self.assertNotContainsRe(result_content, 'Text attachment: log')
2174
self.assertNotContainsRe(result_content, 'test with expected failure')
2176
def test_unexpected_success_has_log(self):
2177
content, result = self.run_subunit_stream('test_unexpected_success')
2178
self.assertContainsRe(content, '(?m)^log$')
2179
self.assertContainsRe(content, 'test with unexpected success')
2180
self.expectFailure('subunit treats "unexpectedSuccess"'
2181
' as a plain success',
2182
self.assertEqual, 1, len(result.unexpectedSuccesses))
2183
self.assertEqual(1, len(result.unexpectedSuccesses))
2184
test = result.unexpectedSuccesses[0]
2185
# RemotedTestCase doesn't preserve the "details"
2186
## self.assertTrue('log' in test.getDetails())
2188
def test_success_has_no_log(self):
2189
content, result = self.run_subunit_stream('test_success')
2190
self.assertEqual(1, result.testsRun)
2191
self.assertNotContainsRe(content, '(?m)^log$')
2192
self.assertNotContainsRe(content, 'this test succeeds')
2195
class TestRunBzr(tests.TestCase):
2200
def _run_bzr_core(self, argv, retcode=0, encoding=None, stdin=None,
2202
"""Override _run_bzr_core to test how it is invoked by run_bzr.
2204
Attempts to run bzr from inside this class don't actually run it.
2206
We test how run_bzr actually invokes bzr in another location. Here we
2207
only need to test that it passes the right parameters to run_bzr.
2209
self.argv = list(argv)
2210
self.retcode = retcode
2211
self.encoding = encoding
2213
self.working_dir = working_dir
2214
return self.retcode, self.out, self.err
2216
def test_run_bzr_error(self):
2217
self.out = "It sure does!\n"
2218
out, err = self.run_bzr_error(['^$'], ['rocks'], retcode=34)
2219
self.assertEqual(['rocks'], self.argv)
2220
self.assertEqual(34, self.retcode)
2221
self.assertEqual('It sure does!\n', out)
2222
self.assertEquals(out, self.out)
2223
self.assertEqual('', err)
2224
self.assertEquals(err, self.err)
2226
def test_run_bzr_error_regexes(self):
2228
self.err = "bzr: ERROR: foobarbaz is not versioned"
2229
out, err = self.run_bzr_error(
2230
["bzr: ERROR: foobarbaz is not versioned"],
2231
['file-id', 'foobarbaz'])
2233
def test_encoding(self):
2234
"""Test that run_bzr passes encoding to _run_bzr_core"""
2235
self.run_bzr('foo bar')
2236
self.assertEqual(None, self.encoding)
2237
self.assertEqual(['foo', 'bar'], self.argv)
2239
self.run_bzr('foo bar', encoding='baz')
2240
self.assertEqual('baz', self.encoding)
2241
self.assertEqual(['foo', 'bar'], self.argv)
2243
def test_retcode(self):
2244
"""Test that run_bzr passes retcode to _run_bzr_core"""
2245
# Default is retcode == 0
2246
self.run_bzr('foo bar')
2247
self.assertEqual(0, self.retcode)
2248
self.assertEqual(['foo', 'bar'], self.argv)
2250
self.run_bzr('foo bar', retcode=1)
2251
self.assertEqual(1, self.retcode)
2252
self.assertEqual(['foo', 'bar'], self.argv)
2254
self.run_bzr('foo bar', retcode=None)
2255
self.assertEqual(None, self.retcode)
2256
self.assertEqual(['foo', 'bar'], self.argv)
2258
self.run_bzr(['foo', 'bar'], retcode=3)
2259
self.assertEqual(3, self.retcode)
2260
self.assertEqual(['foo', 'bar'], self.argv)
2262
def test_stdin(self):
2263
# test that the stdin keyword to run_bzr is passed through to
2264
# _run_bzr_core as-is. We do this by overriding
2265
# _run_bzr_core in this class, and then calling run_bzr,
2266
# which is a convenience function for _run_bzr_core, so
2268
self.run_bzr('foo bar', stdin='gam')
2269
self.assertEqual('gam', self.stdin)
2270
self.assertEqual(['foo', 'bar'], self.argv)
2272
self.run_bzr('foo bar', stdin='zippy')
2273
self.assertEqual('zippy', self.stdin)
2274
self.assertEqual(['foo', 'bar'], self.argv)
2276
def test_working_dir(self):
2277
"""Test that run_bzr passes working_dir to _run_bzr_core"""
2278
self.run_bzr('foo bar')
2279
self.assertEqual(None, self.working_dir)
2280
self.assertEqual(['foo', 'bar'], self.argv)
2282
self.run_bzr('foo bar', working_dir='baz')
2283
self.assertEqual('baz', self.working_dir)
2284
self.assertEqual(['foo', 'bar'], self.argv)
2286
def test_reject_extra_keyword_arguments(self):
2287
self.assertRaises(TypeError, self.run_bzr, "foo bar",
2288
error_regex=['error message'])
2291
class TestRunBzrCaptured(tests.TestCaseWithTransport):
2292
# Does IO when testing the working_dir parameter.
2294
def apply_redirected(self, stdin=None, stdout=None, stderr=None,
2295
a_callable=None, *args, **kwargs):
2297
self.factory_stdin = getattr(bzrlib.ui.ui_factory, "stdin", None)
2298
self.factory = bzrlib.ui.ui_factory
2299
self.working_dir = osutils.getcwd()
2300
stdout.write('foo\n')
2301
stderr.write('bar\n')
2304
def test_stdin(self):
2305
# test that the stdin keyword to _run_bzr_core is passed through to
2306
# apply_redirected as a StringIO. We do this by overriding
2307
# apply_redirected in this class, and then calling _run_bzr_core,
2308
# which calls apply_redirected.
2309
self.run_bzr(['foo', 'bar'], stdin='gam')
2310
self.assertEqual('gam', self.stdin.read())
2311
self.assertTrue(self.stdin is self.factory_stdin)
2312
self.run_bzr(['foo', 'bar'], stdin='zippy')
2313
self.assertEqual('zippy', self.stdin.read())
2314
self.assertTrue(self.stdin is self.factory_stdin)
2316
def test_ui_factory(self):
2317
# each invocation of self.run_bzr should get its
2318
# own UI factory, which is an instance of TestUIFactory,
2319
# with stdin, stdout and stderr attached to the stdin,
2320
# stdout and stderr of the invoked run_bzr
2321
current_factory = bzrlib.ui.ui_factory
2322
self.run_bzr(['foo'])
2323
self.assertFalse(current_factory is self.factory)
2324
self.assertNotEqual(sys.stdout, self.factory.stdout)
2325
self.assertNotEqual(sys.stderr, self.factory.stderr)
2326
self.assertEqual('foo\n', self.factory.stdout.getvalue())
2327
self.assertEqual('bar\n', self.factory.stderr.getvalue())
2328
self.assertIsInstance(self.factory, tests.TestUIFactory)
2330
def test_working_dir(self):
2331
self.build_tree(['one/', 'two/'])
2332
cwd = osutils.getcwd()
2334
# Default is to work in the current directory
2335
self.run_bzr(['foo', 'bar'])
2336
self.assertEqual(cwd, self.working_dir)
2338
self.run_bzr(['foo', 'bar'], working_dir=None)
2339
self.assertEqual(cwd, self.working_dir)
2341
# The function should be run in the alternative directory
2342
# but afterwards the current working dir shouldn't be changed
2343
self.run_bzr(['foo', 'bar'], working_dir='one')
2344
self.assertNotEqual(cwd, self.working_dir)
2345
self.assertEndsWith(self.working_dir, 'one')
2346
self.assertEqual(cwd, osutils.getcwd())
2348
self.run_bzr(['foo', 'bar'], working_dir='two')
2349
self.assertNotEqual(cwd, self.working_dir)
2350
self.assertEndsWith(self.working_dir, 'two')
2351
self.assertEqual(cwd, osutils.getcwd())
2354
class StubProcess(object):
2355
"""A stub process for testing run_bzr_subprocess."""
2357
def __init__(self, out="", err="", retcode=0):
2360
self.returncode = retcode
2362
def communicate(self):
2363
return self.out, self.err
2366
class TestWithFakedStartBzrSubprocess(tests.TestCaseWithTransport):
2367
"""Base class for tests testing how we might run bzr."""
2370
tests.TestCaseWithTransport.setUp(self)
2371
self.subprocess_calls = []
2373
def start_bzr_subprocess(self, process_args, env_changes=None,
2374
skip_if_plan_to_signal=False,
2376
allow_plugins=False):
2377
"""capture what run_bzr_subprocess tries to do."""
2378
self.subprocess_calls.append({'process_args':process_args,
2379
'env_changes':env_changes,
2380
'skip_if_plan_to_signal':skip_if_plan_to_signal,
2381
'working_dir':working_dir, 'allow_plugins':allow_plugins})
2382
return self.next_subprocess
2385
class TestRunBzrSubprocess(TestWithFakedStartBzrSubprocess):
2387
def assertRunBzrSubprocess(self, expected_args, process, *args, **kwargs):
2388
"""Run run_bzr_subprocess with args and kwargs using a stubbed process.
2390
Inside TestRunBzrSubprocessCommands we use a stub start_bzr_subprocess
2391
that will return static results. This assertion method populates those
2392
results and also checks the arguments run_bzr_subprocess generates.
2394
self.next_subprocess = process
2396
result = self.run_bzr_subprocess(*args, **kwargs)
2398
self.next_subprocess = None
2399
for key, expected in expected_args.iteritems():
2400
self.assertEqual(expected, self.subprocess_calls[-1][key])
1840
class TestKnownFailure(TestCase):
1842
def test_known_failure(self):
1843
"""Check that KnownFailure is defined appropriately."""
1844
# a KnownFailure is an assertion error for compatability with unaware
1846
self.assertIsInstance(KnownFailure(""), AssertionError)
1848
def test_expect_failure(self):
1850
self.expectFailure("Doomed to failure", self.assertTrue, False)
1851
except KnownFailure, e:
1852
self.assertEqual('Doomed to failure', e.args[0])
1854
self.expectFailure("Doomed to failure", self.assertTrue, True)
1855
except AssertionError, e:
1856
self.assertEqual('Unexpected success. Should have failed:'
1857
' Doomed to failure', e.args[0])
2403
self.next_subprocess = None
2404
for key, expected in expected_args.iteritems():
2405
self.assertEqual(expected, self.subprocess_calls[-1][key])
2408
def test_run_bzr_subprocess(self):
2409
"""The run_bzr_helper_external command behaves nicely."""
2410
self.assertRunBzrSubprocess({'process_args':['--version']},
2411
StubProcess(), '--version')
2412
self.assertRunBzrSubprocess({'process_args':['--version']},
2413
StubProcess(), ['--version'])
2414
# retcode=None disables retcode checking
2415
result = self.assertRunBzrSubprocess({},
2416
StubProcess(retcode=3), '--version', retcode=None)
2417
result = self.assertRunBzrSubprocess({},
2418
StubProcess(out="is free software"), '--version')
2419
self.assertContainsRe(result[0], 'is free software')
2420
# Running a subcommand that is missing errors
2421
self.assertRaises(AssertionError, self.assertRunBzrSubprocess,
2422
{'process_args':['--versionn']}, StubProcess(retcode=3),
2424
# Unless it is told to expect the error from the subprocess
2425
result = self.assertRunBzrSubprocess({},
2426
StubProcess(retcode=3), '--versionn', retcode=3)
2427
# Or to ignore retcode checking
2428
result = self.assertRunBzrSubprocess({},
2429
StubProcess(err="unknown command", retcode=3), '--versionn',
2431
self.assertContainsRe(result[1], 'unknown command')
2433
def test_env_change_passes_through(self):
2434
self.assertRunBzrSubprocess(
2435
{'env_changes':{'new':'value', 'changed':'newvalue', 'deleted':None}},
2437
env_changes={'new':'value', 'changed':'newvalue', 'deleted':None})
2439
def test_no_working_dir_passed_as_None(self):
2440
self.assertRunBzrSubprocess({'working_dir': None}, StubProcess(), '')
2442
def test_no_working_dir_passed_through(self):
2443
self.assertRunBzrSubprocess({'working_dir': 'dir'}, StubProcess(), '',
2446
def test_run_bzr_subprocess_no_plugins(self):
2447
self.assertRunBzrSubprocess({'allow_plugins': False},
2450
def test_allow_plugins(self):
2451
self.assertRunBzrSubprocess({'allow_plugins': True},
2452
StubProcess(), '', allow_plugins=True)
2455
class TestFinishBzrSubprocess(TestWithFakedStartBzrSubprocess):
2457
def test_finish_bzr_subprocess_with_error(self):
2458
"""finish_bzr_subprocess allows specification of the desired exit code.
2460
process = StubProcess(err="unknown command", retcode=3)
2461
result = self.finish_bzr_subprocess(process, retcode=3)
2462
self.assertEqual('', result[0])
2463
self.assertContainsRe(result[1], 'unknown command')
2465
def test_finish_bzr_subprocess_ignoring_retcode(self):
2466
"""finish_bzr_subprocess allows the exit code to be ignored."""
2467
process = StubProcess(err="unknown command", retcode=3)
2468
result = self.finish_bzr_subprocess(process, retcode=None)
2469
self.assertEqual('', result[0])
2470
self.assertContainsRe(result[1], 'unknown command')
2472
def test_finish_subprocess_with_unexpected_retcode(self):
2473
"""finish_bzr_subprocess raises self.failureException if the retcode is
2474
not the expected one.
2476
process = StubProcess(err="unknown command", retcode=3)
2477
self.assertRaises(self.failureException, self.finish_bzr_subprocess,
2481
class _DontSpawnProcess(Exception):
2482
"""A simple exception which just allows us to skip unnecessary steps"""
2485
class TestStartBzrSubProcess(tests.TestCase):
2487
def check_popen_state(self):
2488
"""Replace to make assertions when popen is called."""
2490
def _popen(self, *args, **kwargs):
2491
"""Record the command that is run, so that we can ensure it is correct"""
2492
self.check_popen_state()
2493
self._popen_args = args
2494
self._popen_kwargs = kwargs
2495
raise _DontSpawnProcess()
2497
def test_run_bzr_subprocess_no_plugins(self):
2498
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [])
2499
command = self._popen_args[0]
2500
self.assertEqual(sys.executable, command[0])
2501
self.assertEqual(self.get_bzr_path(), command[1])
2502
self.assertEqual(['--no-plugins'], command[2:])
2504
def test_allow_plugins(self):
2505
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2507
command = self._popen_args[0]
2508
self.assertEqual([], command[2:])
2510
def test_set_env(self):
2511
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2513
def check_environment():
2514
self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR'])
2515
self.check_popen_state = check_environment
2516
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2517
env_changes={'EXISTANT_ENV_VAR':'set variable'})
2518
# not set in theparent
2519
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2521
def test_run_bzr_subprocess_env_del(self):
2522
"""run_bzr_subprocess can remove environment variables too."""
2523
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2524
def check_environment():
2525
self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2526
os.environ['EXISTANT_ENV_VAR'] = 'set variable'
2527
self.check_popen_state = check_environment
2528
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2529
env_changes={'EXISTANT_ENV_VAR':None})
2530
# Still set in parent
2531
self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR'])
2532
del os.environ['EXISTANT_ENV_VAR']
2534
def test_env_del_missing(self):
2535
self.assertFalse('NON_EXISTANT_ENV_VAR' in os.environ)
2536
def check_environment():
2537
self.assertFalse('NON_EXISTANT_ENV_VAR' in os.environ)
2538
self.check_popen_state = check_environment
2539
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2540
env_changes={'NON_EXISTANT_ENV_VAR':None})
2542
def test_working_dir(self):
2543
"""Test that we can specify the working dir for the child"""
2544
orig_getcwd = osutils.getcwd
2545
orig_chdir = os.chdir
2553
osutils.getcwd = getcwd
2555
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2558
osutils.getcwd = orig_getcwd
2560
os.chdir = orig_chdir
2561
self.assertEqual(['foo', 'current'], chdirs)
2563
def test_get_bzr_path_with_cwd_bzrlib(self):
2564
self.get_source_path = lambda: ""
2565
self.overrideAttr(os.path, "isfile", lambda path: True)
2566
self.assertEqual(self.get_bzr_path(), "bzr")
2569
class TestActuallyStartBzrSubprocess(tests.TestCaseWithTransport):
2570
"""Tests that really need to do things with an external bzr."""
2572
def test_start_and_stop_bzr_subprocess_send_signal(self):
2573
"""finish_bzr_subprocess raises self.failureException if the retcode is
2574
not the expected one.
2576
self.disable_missing_extensions_warning()
2577
process = self.start_bzr_subprocess(['wait-until-signalled'],
2578
skip_if_plan_to_signal=True)
2579
self.assertEqual('running\n', process.stdout.readline())
2580
result = self.finish_bzr_subprocess(process, send_signal=signal.SIGINT,
2582
self.assertEqual('', result[0])
2583
self.assertEqual('bzr: interrupted\n', result[1])
2586
class TestFeature(tests.TestCase):
1859
self.fail('Assertion not raised')
1862
class TestFeature(TestCase):
2588
1864
def test_caching(self):
2589
1865
"""Feature._probe is called by the feature at most once."""
2590
class InstrumentedFeature(tests.Feature):
1866
class InstrumentedFeature(Feature):
2591
1867
def __init__(self):
2592
super(InstrumentedFeature, self).__init__()
1868
Feature.__init__(self)
2593
1869
self.calls = []
2594
1870
def _probe(self):
2595
1871
self.calls.append('_probe')
3187
2364
self.assertEquals('bzrlib.plugins', tpr.resolve_alias('bp'))
3190
class TestThreadLeakDetection(tests.TestCase):
3191
"""Ensure when tests leak threads we detect and report it"""
3193
class LeakRecordingResult(tests.ExtendedTestResult):
3195
tests.ExtendedTestResult.__init__(self, StringIO(), 0, 1)
3197
def _report_thread_leak(self, test, leaks, alive):
3198
self.leaks.append((test, leaks))
3200
def test_testcase_without_addCleanups(self):
3201
"""Check old TestCase instances don't break with leak detection"""
3202
class Test(unittest.TestCase):
3205
result = self.LeakRecordingResult()
3207
result.startTestRun()
3209
result.stopTestRun()
3210
self.assertEqual(result._tests_leaking_threads_count, 0)
3211
self.assertEqual(result.leaks, [])
3213
def test_thread_leak(self):
3214
"""Ensure a thread that outlives the running of a test is reported
3216
Uses a thread that blocks on an event, and is started by the inner
3217
test case. As the thread outlives the inner case's run, it should be
3218
detected as a leak, but the event is then set so that the thread can
3219
be safely joined in cleanup so it's not leaked for real.
3221
event = threading.Event()
3222
thread = threading.Thread(name="Leaker", target=event.wait)
3223
class Test(tests.TestCase):
3224
def test_leak(self):
3226
result = self.LeakRecordingResult()
3227
test = Test("test_leak")
3228
self.addCleanup(thread.join)
3229
self.addCleanup(event.set)
3230
result.startTestRun()
3232
result.stopTestRun()
3233
self.assertEqual(result._tests_leaking_threads_count, 1)
3234
self.assertEqual(result._first_thread_leaker_id, test.id())
3235
self.assertEqual(result.leaks, [(test, set([thread]))])
3236
self.assertContainsString(result.stream.getvalue(), "leaking threads")
3238
def test_multiple_leaks(self):
3239
"""Check multiple leaks are blamed on the test cases at fault
3241
Same concept as the previous test, but has one inner test method that
3242
leaks two threads, and one that doesn't leak at all.
3244
event = threading.Event()
3245
thread_a = threading.Thread(name="LeakerA", target=event.wait)
3246
thread_b = threading.Thread(name="LeakerB", target=event.wait)
3247
thread_c = threading.Thread(name="LeakerC", target=event.wait)
3248
class Test(tests.TestCase):
3249
def test_first_leak(self):
3251
def test_second_no_leak(self):
3253
def test_third_leak(self):
3256
result = self.LeakRecordingResult()
3257
first_test = Test("test_first_leak")
3258
third_test = Test("test_third_leak")
3259
self.addCleanup(thread_a.join)
3260
self.addCleanup(thread_b.join)
3261
self.addCleanup(thread_c.join)
3262
self.addCleanup(event.set)
3263
result.startTestRun()
3265
[first_test, Test("test_second_no_leak"), third_test]
3267
result.stopTestRun()
3268
self.assertEqual(result._tests_leaking_threads_count, 2)
3269
self.assertEqual(result._first_thread_leaker_id, first_test.id())
3270
self.assertEqual(result.leaks, [
3271
(first_test, set([thread_b])),
3272
(third_test, set([thread_a, thread_c]))])
3273
self.assertContainsString(result.stream.getvalue(), "leaking threads")
3276
class TestPostMortemDebugging(tests.TestCase):
3277
"""Check post mortem debugging works when tests fail or error"""
3279
class TracebackRecordingResult(tests.ExtendedTestResult):
3281
tests.ExtendedTestResult.__init__(self, StringIO(), 0, 1)
3282
self.postcode = None
3283
def _post_mortem(self, tb=None):
3284
"""Record the code object at the end of the current traceback"""
3285
tb = tb or sys.exc_info()[2]
3288
while next is not None:
3291
self.postcode = tb.tb_frame.f_code
3292
def report_error(self, test, err):
3294
def report_failure(self, test, err):
3297
def test_location_unittest_error(self):
3298
"""Needs right post mortem traceback with erroring unittest case"""
3299
class Test(unittest.TestCase):
3302
result = self.TracebackRecordingResult()
3304
self.assertEqual(result.postcode, Test.runTest.func_code)
3306
def test_location_unittest_failure(self):
3307
"""Needs right post mortem traceback with failing unittest case"""
3308
class Test(unittest.TestCase):
3310
raise self.failureException
3311
result = self.TracebackRecordingResult()
3313
self.assertEqual(result.postcode, Test.runTest.func_code)
3315
def test_location_bt_error(self):
3316
"""Needs right post mortem traceback with erroring bzrlib.tests case"""
3317
class Test(tests.TestCase):
3318
def test_error(self):
3320
result = self.TracebackRecordingResult()
3321
Test("test_error").run(result)
3322
self.assertEqual(result.postcode, Test.test_error.func_code)
3324
def test_location_bt_failure(self):
3325
"""Needs right post mortem traceback with failing bzrlib.tests case"""
3326
class Test(tests.TestCase):
3327
def test_failure(self):
3328
raise self.failureException
3329
result = self.TracebackRecordingResult()
3330
Test("test_failure").run(result)
3331
self.assertEqual(result.postcode, Test.test_failure.func_code)
3333
def test_env_var_triggers_post_mortem(self):
3334
"""Check pdb.post_mortem is called iff BZR_TEST_PDB is set"""
3336
result = tests.ExtendedTestResult(StringIO(), 0, 1)
3337
post_mortem_calls = []
3338
self.overrideAttr(pdb, "post_mortem", post_mortem_calls.append)
3339
self.overrideEnv('BZR_TEST_PDB', None)
3340
result._post_mortem(1)
3341
self.overrideEnv('BZR_TEST_PDB', 'on')
3342
result._post_mortem(2)
3343
self.assertEqual([2], post_mortem_calls)
3346
class TestRunSuite(tests.TestCase):
2367
class TestRunSuite(TestCase):
3348
2369
def test_runner_class(self):
3349
2370
"""run_suite accepts and uses a runner_class keyword argument."""
3350
class Stub(tests.TestCase):
2371
class Stub(TestCase):
3351
2372
def test_foo(self):
3353
2374
suite = Stub("test_foo")
3355
class MyRunner(tests.TextTestRunner):
2376
class MyRunner(TextTestRunner):
3356
2377
def run(self, test):
3357
2378
calls.append(test)
3358
return tests.ExtendedTestResult(self.stream, self.descriptions,
3360
tests.run_suite(suite, runner_class=MyRunner, stream=StringIO())
3361
self.assertLength(1, calls)
3364
class TestEnvironHandling(tests.TestCase):
3366
def test_overrideEnv_None_called_twice_doesnt_leak(self):
3367
self.assertFalse('MYVAR' in os.environ)
3368
self.overrideEnv('MYVAR', '42')
3369
# We use an embedded test to make sure we fix the _captureVar bug
3370
class Test(tests.TestCase):
3372
# The first call save the 42 value
3373
self.overrideEnv('MYVAR', None)
3374
self.assertEquals(None, os.environ.get('MYVAR'))
3375
# Make sure we can call it twice
3376
self.overrideEnv('MYVAR', None)
3377
self.assertEquals(None, os.environ.get('MYVAR'))
3379
result = tests.TextTestResult(output, 0, 1)
3380
Test('test_me').run(result)
3381
if not result.wasStrictlySuccessful():
3382
self.fail(output.getvalue())
3383
# We get our value back
3384
self.assertEquals('42', os.environ.get('MYVAR'))
3387
class TestIsolatedEnv(tests.TestCase):
3388
"""Test isolating tests from os.environ.
3390
Since we use tests that are already isolated from os.environ a bit of care
3391
should be taken when designing the tests to avoid bootstrap side-effects.
3392
The tests start an already clean os.environ which allow doing valid
3393
assertions about which variables are present or not and design tests around
3397
class ScratchMonkey(tests.TestCase):
2379
return ExtendedTestResult(self.stream, self.descriptions,
2381
run_suite(suite, runner_class=MyRunner, stream=StringIO())
2382
self.assertEqual(calls, [suite])
2384
def test_done(self):
2385
"""run_suite should call result.done()"""
2387
def one_more_call(): self.calls += 1
2388
def test_function():
3402
def test_basics(self):
3403
# Make sure we know the definition of BZR_HOME: not part of os.environ
3404
# for tests.TestCase.
3405
self.assertTrue('BZR_HOME' in tests.isolated_environ)
3406
self.assertEquals(None, tests.isolated_environ['BZR_HOME'])
3407
# Being part of isolated_environ, BZR_HOME should not appear here
3408
self.assertFalse('BZR_HOME' in os.environ)
3409
# Make sure we know the definition of LINES: part of os.environ for
3411
self.assertTrue('LINES' in tests.isolated_environ)
3412
self.assertEquals('25', tests.isolated_environ['LINES'])
3413
self.assertEquals('25', os.environ['LINES'])
3415
def test_injecting_unknown_variable(self):
3416
# BZR_HOME is known to be absent from os.environ
3417
test = self.ScratchMonkey('test_me')
3418
tests.override_os_environ(test, {'BZR_HOME': 'foo'})
3419
self.assertEquals('foo', os.environ['BZR_HOME'])
3420
tests.restore_os_environ(test)
3421
self.assertFalse('BZR_HOME' in os.environ)
3423
def test_injecting_known_variable(self):
3424
test = self.ScratchMonkey('test_me')
3425
# LINES is known to be present in os.environ
3426
tests.override_os_environ(test, {'LINES': '42'})
3427
self.assertEquals('42', os.environ['LINES'])
3428
tests.restore_os_environ(test)
3429
self.assertEquals('25', os.environ['LINES'])
3431
def test_deleting_variable(self):
3432
test = self.ScratchMonkey('test_me')
3433
# LINES is known to be present in os.environ
3434
tests.override_os_environ(test, {'LINES': None})
3435
self.assertTrue('LINES' not in os.environ)
3436
tests.restore_os_environ(test)
3437
self.assertEquals('25', os.environ['LINES'])
3440
class TestDocTestSuiteIsolation(tests.TestCase):
3441
"""Test that `tests.DocTestSuite` isolates doc tests from os.environ.
3443
Since tests.TestCase alreay provides an isolation from os.environ, we use
3444
the clean environment as a base for testing. To precisely capture the
3445
isolation provided by tests.DocTestSuite, we use doctest.DocTestSuite to
3448
We want to make sure `tests.DocTestSuite` respect `tests.isolated_environ`,
3449
not `os.environ` so each test overrides it to suit its needs.
3453
def get_doctest_suite_for_string(self, klass, string):
3454
class Finder(doctest.DocTestFinder):
3456
def find(*args, **kwargs):
3457
test = doctest.DocTestParser().get_doctest(
3458
string, {}, 'foo', 'foo.py', 0)
3461
suite = klass(test_finder=Finder())
3464
def run_doctest_suite_for_string(self, klass, string):
3465
suite = self.get_doctest_suite_for_string(klass, string)
3467
result = tests.TextTestResult(output, 0, 1)
3469
return result, output
3471
def assertDocTestStringSucceds(self, klass, string):
3472
result, output = self.run_doctest_suite_for_string(klass, string)
3473
if not result.wasStrictlySuccessful():
3474
self.fail(output.getvalue())
3476
def assertDocTestStringFails(self, klass, string):
3477
result, output = self.run_doctest_suite_for_string(klass, string)
3478
if result.wasStrictlySuccessful():
3479
self.fail(output.getvalue())
3481
def test_injected_variable(self):
3482
self.overrideAttr(tests, 'isolated_environ', {'LINES': '42'})
3485
>>> os.environ['LINES']
3488
# doctest.DocTestSuite fails as it sees '25'
3489
self.assertDocTestStringFails(doctest.DocTestSuite, test)
3490
# tests.DocTestSuite sees '42'
3491
self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
3493
def test_deleted_variable(self):
3494
self.overrideAttr(tests, 'isolated_environ', {'LINES': None})
3497
>>> os.environ.get('LINES')
3499
# doctest.DocTestSuite fails as it sees '25'
3500
self.assertDocTestStringFails(doctest.DocTestSuite, test)
3501
# tests.DocTestSuite sees None
3502
self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
2390
test = unittest.FunctionTestCase(test_function)
2391
class InstrumentedTestResult(ExtendedTestResult):
2392
def done(self): one_more_call()
2393
class MyRunner(TextTestRunner):
2394
def run(self, test):
2395
return InstrumentedTestResult(self.stream, self.descriptions,
2397
run_suite(test, runner_class=MyRunner, stream=StringIO())
2398
self.assertEquals(1, self.calls)