350
353
{'bzrdir_format': formats[1]._matchingbzrdir,
351
354
'transport_readonly_server': 'b',
352
355
'transport_server': 'a',
353
'workingtree_format': formats[1]}),
354
('WorkingTreeFormat6',
355
{'bzrdir_format': formats[2]._matchingbzrdir,
356
'transport_readonly_server': 'b',
357
'transport_server': 'a',
358
'workingtree_format': formats[2]}),
359
('WorkingTreeFormat6,remote',
360
{'bzrdir_format': formats[2]._matchingbzrdir,
361
'repo_is_remote': True,
362
'transport_readonly_server': 'd',
363
'transport_server': 'c',
364
'vfs_transport_factory': 'e',
365
'workingtree_format': formats[2]}),
356
'workingtree_format': formats[1]})],
369
360
class TestTreeScenarios(tests.TestCase):
371
362
def test_scenarios(self):
372
363
# the tree implementation scenario generator is meant to setup one
373
# instance for each working tree format, one additional instance
364
# instance for each working tree format, and one additional instance
374
365
# that will use the default wt format, but create a revision tree for
375
# the tests, and one more that uses the default wt format as a
376
# lightweight checkout of a remote repository. This means that the wt
377
# ones should have the workingtree_to_test_tree attribute set to
378
# 'return_parameter' and the revision one set to
379
# revision_tree_from_workingtree.
366
# the tests. this means that the wt ones should have the
367
# workingtree_to_test_tree attribute set to 'return_parameter' and the
368
# revision one set to revision_tree_from_workingtree.
381
370
from bzrlib.tests.per_tree import (
382
371
_dirstate_tree_from_workingtree,
890
_get_test("test_xfail").run(result)
891
self.assertContainsRe(result_stream.getvalue(),
892
"\n\\S+\\.test_xfail\\s+XFAIL\\s+\\d+ms\n"
893
"\\s*(?:Text attachment: )?reason"
866
test = self.get_passing_test()
867
result.startTest(test)
868
prefix = len(result_stream.getvalue())
869
# the err parameter has the shape:
870
# (class, exception object, traceback)
871
# KnownFailures dont get their tracebacks shown though, so we
873
err = (tests.KnownFailure, tests.KnownFailure('foo'), None)
874
result.report_known_failure(test, err)
875
output = result_stream.getvalue()[prefix:]
876
lines = output.splitlines()
877
self.assertContainsRe(lines[0], r'XFAIL *\d+ms$')
878
if sys.version_info > (2, 7):
879
self.expectFailure("_ExpectedFailure on 2.7 loses the message",
880
self.assertNotEqual, lines[1], ' ')
881
self.assertEqual(lines[1], ' foo')
882
self.assertEqual(2, len(lines))
898
884
def get_passing_test(self):
899
885
"""Return a test object that can't be run usefully."""
1507
1482
transport_server = memory.MemoryServer()
1508
1483
transport_server.start_server()
1509
1484
self.addCleanup(transport_server.stop_server)
1510
t = transport.get_transport_from_url(transport_server.get_url())
1511
controldir.ControlDir.create(t.base)
1485
t = transport.get_transport(transport_server.get_url())
1486
bzrdir.BzrDir.create(t.base)
1512
1487
self.assertRaises(errors.BzrError,
1513
controldir.ControlDir.open_from_transport, t)
1488
bzrdir.BzrDir.open_from_transport, t)
1514
1489
# But if we declare this as safe, we can open the bzrdir.
1515
1490
self.permit_url(t.base)
1516
1491
self._bzr_selftest_roots.append(t.base)
1517
controldir.ControlDir.open_from_transport(t)
1492
bzrdir.BzrDir.open_from_transport(t)
1519
1494
def test_requireFeature_available(self):
1520
1495
"""self.requireFeature(available) is a no-op."""
1521
class Available(features.Feature):
1496
class Available(tests.Feature):
1522
1497
def _probe(self):return True
1523
1498
feature = Available()
1524
1499
self.requireFeature(feature)
1526
1501
def test_requireFeature_unavailable(self):
1527
1502
"""self.requireFeature(unavailable) raises UnavailableFeature."""
1528
class Unavailable(features.Feature):
1503
class Unavailable(tests.Feature):
1529
1504
def _probe(self):return False
1530
1505
feature = Unavailable()
1531
1506
self.assertRaises(tests.UnavailableFeature,
1684
1654
class Test(tests.TestCase):
1686
1656
def setUp(self):
1687
super(Test, self).setUp()
1657
tests.TestCase.setUp(self)
1688
1658
self.orig = self.overrideAttr(obj, 'test_attr', new='modified')
1690
1660
def test_value(self):
1691
1661
self.assertEqual('original', self.orig)
1692
1662
self.assertEqual('modified', obj.test_attr)
1694
self._run_successful_test(Test('test_value'))
1664
test = Test('test_value')
1665
test.run(unittest.TestResult())
1695
1666
self.assertEqual('original', obj.test_attr)
1697
def test_overrideAttr_with_no_existing_value_and_value(self):
1698
# Do not define the test_attribute
1699
obj = self # Make 'obj' visible to the embedded test
1700
class Test(tests.TestCase):
1703
tests.TestCase.setUp(self)
1704
self.orig = self.overrideAttr(obj, 'test_attr', new='modified')
1706
def test_value(self):
1707
self.assertEqual(tests._unitialized_attr, self.orig)
1708
self.assertEqual('modified', obj.test_attr)
1710
self._run_successful_test(Test('test_value'))
1711
self.assertRaises(AttributeError, getattr, obj, 'test_attr')
1713
def test_overrideAttr_with_no_existing_value_and_no_value(self):
1714
# Do not define the test_attribute
1715
obj = self # Make 'obj' visible to the embedded test
1716
class Test(tests.TestCase):
1719
tests.TestCase.setUp(self)
1720
self.orig = self.overrideAttr(obj, 'test_attr')
1722
def test_value(self):
1723
self.assertEqual(tests._unitialized_attr, self.orig)
1724
self.assertRaises(AttributeError, getattr, obj, 'test_attr')
1726
self._run_successful_test(Test('test_value'))
1727
self.assertRaises(AttributeError, getattr, obj, 'test_attr')
1729
def test_recordCalls(self):
1730
from bzrlib.tests import test_selftest
1731
calls = self.recordCalls(
1732
test_selftest, '_add_numbers')
1733
self.assertEqual(test_selftest._add_numbers(2, 10),
1735
self.assertEqual(calls, [((2, 10), {})])
1738
def _add_numbers(a, b):
1742
class _MissingFeature(features.Feature):
1669
class _MissingFeature(tests.Feature):
1743
1670
def _probe(self):
1745
1672
missing_feature = _MissingFeature()
1796
1723
result = self._run_test('test_fail')
1797
1724
self.assertEqual(1, len(result.failures))
1798
1725
result_content = result.failures[0][1]
1799
self.assertContainsRe(result_content,
1800
'(?m)^(?:Text attachment: )?log(?:$|: )')
1726
self.assertContainsRe(result_content, 'Text attachment: log')
1801
1727
self.assertContainsRe(result_content, 'this was a failing test')
1803
1729
def test_error_has_log(self):
1804
1730
result = self._run_test('test_error')
1805
1731
self.assertEqual(1, len(result.errors))
1806
1732
result_content = result.errors[0][1]
1807
self.assertContainsRe(result_content,
1808
'(?m)^(?:Text attachment: )?log(?:$|: )')
1733
self.assertContainsRe(result_content, 'Text attachment: log')
1809
1734
self.assertContainsRe(result_content, 'this test errored')
1811
1736
def test_skip_has_no_log(self):
2246
2170
self.assertNotContainsRe(content, 'test with expected failure')
2247
2171
self.assertEqual(1, len(result.expectedFailures))
2248
2172
result_content = result.expectedFailures[0][1]
2249
self.assertNotContainsRe(result_content,
2250
'(?m)^(?:Text attachment: )?log(?:$|: )')
2173
self.assertNotContainsRe(result_content, 'Text attachment: log')
2251
2174
self.assertNotContainsRe(result_content, 'test with expected failure')
2253
2176
def test_unexpected_success_has_log(self):
2254
2177
content, result = self.run_subunit_stream('test_unexpected_success')
2255
2178
self.assertContainsRe(content, '(?m)^log$')
2256
2179
self.assertContainsRe(content, 'test with unexpected success')
2257
# GZ 2011-05-18: Old versions of subunit treat unexpected success as a
2258
# success, if a min version check is added remove this
2259
from subunit import TestProtocolClient as _Client
2260
if _Client.addUnexpectedSuccess.im_func is _Client.addSuccess.im_func:
2261
self.expectFailure('subunit treats "unexpectedSuccess"'
2262
' as a plain success',
2263
self.assertEqual, 1, len(result.unexpectedSuccesses))
2180
self.expectFailure('subunit treats "unexpectedSuccess"'
2181
' as a plain success',
2182
self.assertEqual, 1, len(result.unexpectedSuccesses))
2264
2183
self.assertEqual(1, len(result.unexpectedSuccesses))
2265
2184
test = result.unexpectedSuccesses[0]
2266
2185
# RemotedTestCase doesn't preserve the "details"
2566
2485
class TestStartBzrSubProcess(tests.TestCase):
2567
"""Stub test start_bzr_subprocess."""
2569
def _subprocess_log_cleanup(self):
2570
"""Inhibits the base version as we don't produce a log file."""
2487
def check_popen_state(self):
2488
"""Replace to make assertions when popen is called."""
2572
2490
def _popen(self, *args, **kwargs):
2573
"""Override the base version to record the command that is run.
2575
From there we can ensure it is correct without spawning a real process.
2491
"""Record the command that is run, so that we can ensure it is correct"""
2577
2492
self.check_popen_state()
2578
2493
self._popen_args = args
2579
2494
self._popen_kwargs = kwargs
2580
2495
raise _DontSpawnProcess()
2582
def check_popen_state(self):
2583
"""Replace to make assertions when popen is called."""
2585
2497
def test_run_bzr_subprocess_no_plugins(self):
2586
2498
self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [])
2587
2499
command = self._popen_args[0]
2665
2583
self.assertEqual('bzr: interrupted\n', result[1])
2586
class TestFeature(tests.TestCase):
2588
def test_caching(self):
2589
"""Feature._probe is called by the feature at most once."""
2590
class InstrumentedFeature(tests.Feature):
2592
super(InstrumentedFeature, self).__init__()
2595
self.calls.append('_probe')
2597
feature = InstrumentedFeature()
2599
self.assertEqual(['_probe'], feature.calls)
2601
self.assertEqual(['_probe'], feature.calls)
2603
def test_named_str(self):
2604
"""Feature.__str__ should thunk to feature_name()."""
2605
class NamedFeature(tests.Feature):
2606
def feature_name(self):
2608
feature = NamedFeature()
2609
self.assertEqual('symlinks', str(feature))
2611
def test_default_str(self):
2612
"""Feature.__str__ should default to __class__.__name__."""
2613
class NamedFeature(tests.Feature):
2615
feature = NamedFeature()
2616
self.assertEqual('NamedFeature', str(feature))
2619
class TestUnavailableFeature(tests.TestCase):
2621
def test_access_feature(self):
2622
feature = tests.Feature()
2623
exception = tests.UnavailableFeature(feature)
2624
self.assertIs(feature, exception.args[0])
2627
simple_thunk_feature = tests._CompatabilityThunkFeature(
2628
deprecated_in((2, 1, 0)),
2629
'bzrlib.tests.test_selftest',
2630
'simple_thunk_feature','UnicodeFilename',
2631
replacement_module='bzrlib.tests'
2634
class Test_CompatibilityFeature(tests.TestCase):
2636
def test_does_thunk(self):
2637
res = self.callDeprecated(
2638
['bzrlib.tests.test_selftest.simple_thunk_feature was deprecated'
2639
' in version 2.1.0. Use bzrlib.tests.UnicodeFilename instead.'],
2640
simple_thunk_feature.available)
2641
self.assertEqual(tests.UnicodeFilename.available(), res)
2644
class TestModuleAvailableFeature(tests.TestCase):
2646
def test_available_module(self):
2647
feature = tests.ModuleAvailableFeature('bzrlib.tests')
2648
self.assertEqual('bzrlib.tests', feature.module_name)
2649
self.assertEqual('bzrlib.tests', str(feature))
2650
self.assertTrue(feature.available())
2651
self.assertIs(tests, feature.module)
2653
def test_unavailable_module(self):
2654
feature = tests.ModuleAvailableFeature('bzrlib.no_such_module_exists')
2655
self.assertEqual('bzrlib.no_such_module_exists', str(feature))
2656
self.assertFalse(feature.available())
2657
self.assertIs(None, feature.module)
2668
2660
class TestSelftestFiltering(tests.TestCase):
2670
2662
def setUp(self):
2671
super(TestSelftestFiltering, self).setUp()
2663
tests.TestCase.setUp(self)
2672
2664
self.suite = TestUtil.TestSuite()
2673
2665
self.loader = TestUtil.TestLoader()
2674
2666
self.suite.addTest(self.loader.loadTestsFromModule(
3134
3126
loader = self._create_loader('bzrlib.tests.test_samp')
3136
3128
suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
3137
self.assertEqual(test_list, _test_ids(suite))
3129
self.assertEquals(test_list, _test_ids(suite))
3139
3131
def test_load_tests_inside_module(self):
3140
3132
test_list = ['bzrlib.tests.test_sampler.DemoTest.test_nothing']
3141
3133
loader = self._create_loader('bzrlib.tests.test_sampler.Demo')
3143
3135
suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
3144
self.assertEqual(test_list, _test_ids(suite))
3136
self.assertEquals(test_list, _test_ids(suite))
3146
3138
def test_exclude_tests(self):
3147
3139
test_list = ['bogus']
3148
3140
loader = self._create_loader('bogus')
3150
3142
suite = loader.loadTestsFromModuleName('bzrlib.tests.test_sampler')
3151
self.assertEqual([], _test_ids(suite))
3143
self.assertEquals([], _test_ids(suite))
3154
3146
class TestTestPrefixRegistry(tests.TestCase):
3188
3180
def test_predefined_prefixes(self):
3189
3181
tpr = tests.test_prefix_alias_registry
3190
self.assertEqual('bzrlib', tpr.resolve_alias('bzrlib'))
3191
self.assertEqual('bzrlib.doc', tpr.resolve_alias('bd'))
3192
self.assertEqual('bzrlib.utils', tpr.resolve_alias('bu'))
3193
self.assertEqual('bzrlib.tests', tpr.resolve_alias('bt'))
3194
self.assertEqual('bzrlib.tests.blackbox', tpr.resolve_alias('bb'))
3195
self.assertEqual('bzrlib.plugins', tpr.resolve_alias('bp'))
3182
self.assertEquals('bzrlib', tpr.resolve_alias('bzrlib'))
3183
self.assertEquals('bzrlib.doc', tpr.resolve_alias('bd'))
3184
self.assertEquals('bzrlib.utils', tpr.resolve_alias('bu'))
3185
self.assertEquals('bzrlib.tests', tpr.resolve_alias('bt'))
3186
self.assertEquals('bzrlib.tests.blackbox', tpr.resolve_alias('bb'))
3187
self.assertEquals('bzrlib.plugins', tpr.resolve_alias('bp'))
3198
3190
class TestThreadLeakDetection(tests.TestCase):
3369
3361
self.assertLength(1, calls)
3372
class _Selftest(object):
3373
"""Mixin for tests needing full selftest output"""
3375
def _inject_stream_into_subunit(self, stream):
3376
"""To be overridden by subclasses that run tests out of process"""
3378
def _run_selftest(self, **kwargs):
3380
self._inject_stream_into_subunit(sio)
3381
tests.selftest(stream=sio, stop_on_failure=False, **kwargs)
3382
return sio.getvalue()
3385
class _ForkedSelftest(_Selftest):
3386
"""Mixin for tests needing full selftest output with forked children"""
3388
_test_needs_features = [features.subunit]
3390
def _inject_stream_into_subunit(self, stream):
3391
"""Monkey-patch subunit so the extra output goes to stream not stdout
3393
Some APIs need rewriting so this kind of bogus hackery can be replaced
3394
by passing the stream param from run_tests down into ProtocolTestCase.
3396
from subunit import ProtocolTestCase
3397
_original_init = ProtocolTestCase.__init__
3398
def _init_with_passthrough(self, *args, **kwargs):
3399
_original_init(self, *args, **kwargs)
3400
self._passthrough = stream
3401
self.overrideAttr(ProtocolTestCase, "__init__", _init_with_passthrough)
3403
def _run_selftest(self, **kwargs):
3404
# GZ 2011-05-26: Add a PosixSystem feature so this check can go away
3405
if getattr(os, "fork", None) is None:
3406
raise tests.TestNotApplicable("Platform doesn't support forking")
3407
# Make sure the fork code is actually invoked by claiming two cores
3408
self.overrideAttr(osutils, "local_concurrency", lambda: 2)
3409
kwargs.setdefault("suite_decorators", []).append(tests.fork_decorator)
3410
return super(_ForkedSelftest, self)._run_selftest(**kwargs)
3413
class TestParallelFork(_ForkedSelftest, tests.TestCase):
3414
"""Check operation of --parallel=fork selftest option"""
3416
def test_error_in_child_during_fork(self):
3417
"""Error in a forked child during test setup should get reported"""
3418
class Test(tests.TestCase):
3419
def testMethod(self):
3421
# We don't care what, just break something that a child will run
3422
self.overrideAttr(tests, "workaround_zealous_crypto_random", None)
3423
out = self._run_selftest(test_suite_factory=Test)
3424
# Lines from the tracebacks of the two child processes may be mixed
3425
# together due to the way subunit parses and forwards the streams,
3426
# so permit extra lines between each part of the error output.
3427
self.assertContainsRe(out,
3430
".+ in fork_for_tests\n"
3432
"\s*workaround_zealous_crypto_random\(\)\n"
3437
class TestUncollectedWarnings(_Selftest, tests.TestCase):
3438
"""Check a test case still alive after being run emits a warning"""
3440
class Test(tests.TestCase):
3441
def test_pass(self):
3443
def test_self_ref(self):
3444
self.also_self = self.test_self_ref
3445
def test_skip(self):
3446
self.skip("Don't need")
3448
def _get_suite(self):
3449
return TestUtil.TestSuite([
3450
self.Test("test_pass"),
3451
self.Test("test_self_ref"),
3452
self.Test("test_skip"),
3455
def _run_selftest_with_suite(self, **kwargs):
3456
old_flags = tests.selftest_debug_flags
3457
tests.selftest_debug_flags = old_flags.union(["uncollected_cases"])
3458
gc_on = gc.isenabled()
3462
output = self._run_selftest(test_suite_factory=self._get_suite,
3467
tests.selftest_debug_flags = old_flags
3468
self.assertNotContainsRe(output, "Uncollected test case.*test_pass")
3469
self.assertContainsRe(output, "Uncollected test case.*test_self_ref")
3472
def test_testsuite(self):
3473
self._run_selftest_with_suite()
3475
def test_pattern(self):
3476
out = self._run_selftest_with_suite(pattern="test_(?:pass|self_ref)$")
3477
self.assertNotContainsRe(out, "test_skip")
3479
def test_exclude_pattern(self):
3480
out = self._run_selftest_with_suite(exclude_pattern="test_skip$")
3481
self.assertNotContainsRe(out, "test_skip")
3483
def test_random_seed(self):
3484
self._run_selftest_with_suite(random_seed="now")
3486
def test_matching_tests_first(self):
3487
self._run_selftest_with_suite(matching_tests_first=True,
3488
pattern="test_self_ref$")
3490
def test_starting_with_and_exclude(self):
3491
out = self._run_selftest_with_suite(starting_with=["bt."],
3492
exclude_pattern="test_skip$")
3493
self.assertNotContainsRe(out, "test_skip")
3495
def test_additonal_decorator(self):
3496
out = self._run_selftest_with_suite(
3497
suite_decorators=[tests.TestDecorator])
3500
class TestUncollectedWarningsSubunit(TestUncollectedWarnings):
3501
"""Check warnings from tests staying alive are emitted with subunit"""
3503
_test_needs_features = [features.subunit]
3505
def _run_selftest_with_suite(self, **kwargs):
3506
return TestUncollectedWarnings._run_selftest_with_suite(self,
3507
runner_class=tests.SubUnitBzrRunner, **kwargs)
3510
class TestUncollectedWarningsForked(_ForkedSelftest, TestUncollectedWarnings):
3511
"""Check warnings from tests staying alive are emitted when forking"""
3514
3364
class TestEnvironHandling(tests.TestCase):
3516
3366
def test_overrideEnv_None_called_twice_doesnt_leak(self):
3521
3371
def test_me(self):
3522
3372
# The first call save the 42 value
3523
3373
self.overrideEnv('MYVAR', None)
3524
self.assertEqual(None, os.environ.get('MYVAR'))
3374
self.assertEquals(None, os.environ.get('MYVAR'))
3525
3375
# Make sure we can call it twice
3526
3376
self.overrideEnv('MYVAR', None)
3527
self.assertEqual(None, os.environ.get('MYVAR'))
3377
self.assertEquals(None, os.environ.get('MYVAR'))
3528
3378
output = StringIO()
3529
3379
result = tests.TextTestResult(output, 0, 1)
3530
3380
Test('test_me').run(result)
3531
3381
if not result.wasStrictlySuccessful():
3532
3382
self.fail(output.getvalue())
3533
3383
# We get our value back
3534
self.assertEqual('42', os.environ.get('MYVAR'))
3384
self.assertEquals('42', os.environ.get('MYVAR'))
3537
3387
class TestIsolatedEnv(tests.TestCase):
3553
3403
# Make sure we know the definition of BZR_HOME: not part of os.environ
3554
3404
# for tests.TestCase.
3555
3405
self.assertTrue('BZR_HOME' in tests.isolated_environ)
3556
self.assertEqual(None, tests.isolated_environ['BZR_HOME'])
3406
self.assertEquals(None, tests.isolated_environ['BZR_HOME'])
3557
3407
# Being part of isolated_environ, BZR_HOME should not appear here
3558
3408
self.assertFalse('BZR_HOME' in os.environ)
3559
3409
# Make sure we know the definition of LINES: part of os.environ for
3560
3410
# tests.TestCase
3561
3411
self.assertTrue('LINES' in tests.isolated_environ)
3562
self.assertEqual('25', tests.isolated_environ['LINES'])
3563
self.assertEqual('25', os.environ['LINES'])
3412
self.assertEquals('25', tests.isolated_environ['LINES'])
3413
self.assertEquals('25', os.environ['LINES'])
3565
3415
def test_injecting_unknown_variable(self):
3566
3416
# BZR_HOME is known to be absent from os.environ
3567
3417
test = self.ScratchMonkey('test_me')
3568
3418
tests.override_os_environ(test, {'BZR_HOME': 'foo'})
3569
self.assertEqual('foo', os.environ['BZR_HOME'])
3419
self.assertEquals('foo', os.environ['BZR_HOME'])
3570
3420
tests.restore_os_environ(test)
3571
3421
self.assertFalse('BZR_HOME' in os.environ)
3650
3500
self.assertDocTestStringFails(doctest.DocTestSuite, test)
3651
3501
# tests.DocTestSuite sees None
3652
3502
self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
3655
class TestSelftestExcludePatterns(tests.TestCase):
3658
super(TestSelftestExcludePatterns, self).setUp()
3659
self.overrideAttr(tests, 'test_suite', self.suite_factory)
3661
def suite_factory(self, keep_only=None, starting_with=None):
3662
"""A test suite factory with only a few tests."""
3663
class Test(tests.TestCase):
3665
# We don't need the full class path
3666
return self._testMethodName
3673
return TestUtil.TestSuite([Test("a"), Test("b"), Test("c")])
3675
def assertTestList(self, expected, *selftest_args):
3676
# We rely on setUp installing the right test suite factory so we can
3677
# test at the command level without loading the whole test suite
3678
out, err = self.run_bzr(('selftest', '--list') + selftest_args)
3679
actual = out.splitlines()
3680
self.assertEqual(expected, actual)
3682
def test_full_list(self):
3683
self.assertTestList(['a', 'b', 'c'])
3685
def test_single_exclude(self):
3686
self.assertTestList(['b', 'c'], '-x', 'a')
3688
def test_mutiple_excludes(self):
3689
self.assertTestList(['c'], '-x', 'a', '-x', 'b')
3692
class TestCounterHooks(tests.TestCase, SelfTestHelper):
3694
_test_needs_features = [features.subunit]
3697
super(TestCounterHooks, self).setUp()
3698
class Test(tests.TestCase):
3701
super(Test, self).setUp()
3702
self.hooks = hooks.Hooks()
3703
self.hooks.add_hook('myhook', 'Foo bar blah', (2,4))
3704
self.install_counter_hook(self.hooks, 'myhook')
3709
def run_hook_once(self):
3710
for hook in self.hooks['myhook']:
3713
self.test_class = Test
3715
def assertHookCalls(self, expected_calls, test_name):
3716
test = self.test_class(test_name)
3717
result = unittest.TestResult()
3719
self.assertTrue(hasattr(test, '_counters'))
3720
self.assertTrue(test._counters.has_key('myhook'))
3721
self.assertEqual(expected_calls, test._counters['myhook'])
3723
def test_no_hook(self):
3724
self.assertHookCalls(0, 'no_hook')
3726
def test_run_hook_once(self):
3727
tt = features.testtools
3728
if tt.module.__version__ < (0, 9, 8):
3729
raise tests.TestSkipped('testtools-0.9.8 required for addDetail')
3730
self.assertHookCalls(1, 'run_hook_once')