~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_selftest.py

  • Committer: Martin
  • Date: 2011-05-21 16:29:38 UTC
  • mto: This revision was merged to the branch mainline in revision 5907.
  • Revision ID: gzlist@googlemail.com-20110521162938-1vrw3hp0197l3vrl
Add tests for non-ascii conflict serialisation

Show diffs side-by-side

added added

removed removed

Lines of Context:
29
29
from testtools import (
30
30
    ExtendedToOriginalDecorator,
31
31
    MultiTestResult,
32
 
    __version__ as testtools_version,
33
32
    )
34
33
from testtools.content import Content
35
34
from testtools.content_type import ContentType
37
36
    DocTestMatches,
38
37
    Equals,
39
38
    )
40
 
import testtools.testresult.doubles
 
39
import testtools.tests.helpers
41
40
 
42
41
import bzrlib
43
42
from bzrlib import (
44
43
    branchbuilder,
45
44
    bzrdir,
46
45
    errors,
47
 
    hooks,
48
46
    lockdir,
49
47
    memorytree,
50
48
    osutils,
94
92
            DocTestMatches(u"...a test message\n", doctest.ELLIPSIS))
95
93
 
96
94
 
 
95
class TestUnicodeFilename(tests.TestCase):
 
96
 
 
97
    def test_probe_passes(self):
 
98
        """UnicodeFilename._probe passes."""
 
99
        # We can't test much more than that because the behaviour depends
 
100
        # on the platform.
 
101
        tests.UnicodeFilename._probe()
 
102
 
 
103
 
97
104
class TestTreeShape(tests.TestCaseInTempDir):
98
105
 
99
106
    def test_unicode_paths(self):
100
 
        self.requireFeature(features.UnicodeFilenameFeature)
 
107
        self.requireFeature(tests.UnicodeFilename)
101
108
 
102
109
        filename = u'hell\u00d8'
103
110
        self.build_tree_contents([(filename, 'contents of hello')])
713
720
class TestProfileResult(tests.TestCase):
714
721
 
715
722
    def test_profiles_tests(self):
716
 
        self.requireFeature(features.lsprof_feature)
717
 
        terminal = testtools.testresult.doubles.ExtendedTestResult()
 
723
        self.requireFeature(test_lsprof.LSProfFeature)
 
724
        terminal = testtools.tests.helpers.ExtendedTestResult()
718
725
        result = tests.ProfileResult(terminal)
719
726
        class Sample(tests.TestCase):
720
727
            def a(self):
737
744
                descriptions=0,
738
745
                verbosity=1,
739
746
                )
740
 
        capture = testtools.testresult.doubles.ExtendedTestResult()
 
747
        capture = testtools.tests.helpers.ExtendedTestResult()
741
748
        test_case.run(MultiTestResult(result, capture))
742
749
        run_case = capture._events[0][1]
743
750
        timed_string = result._testTimeString(run_case)
774
781
 
775
782
    def test_lsprofiling(self):
776
783
        """Verbose test result prints lsprof statistics from test cases."""
777
 
        self.requireFeature(features.lsprof_feature)
 
784
        self.requireFeature(test_lsprof.LSProfFeature)
778
785
        result_stream = StringIO()
779
786
        result = bzrlib.tests.VerboseTestResult(
780
787
            result_stream,
825
832
        self.assertEndsWith(sio.getvalue(), "OK    50002ms\n")
826
833
 
827
834
    def test_known_failure(self):
828
 
        """Using knownFailure should trigger several result actions."""
 
835
        """A KnownFailure being raised should trigger several result actions."""
829
836
        class InstrumentedTestResult(tests.ExtendedTestResult):
830
837
            def stopTestRun(self): pass
831
838
            def report_tests_starting(self): pass
834
841
        result = InstrumentedTestResult(None, None, None, None)
835
842
        class Test(tests.TestCase):
836
843
            def test_function(self):
837
 
                self.knownFailure('failed!')
 
844
                raise tests.KnownFailure('failed!')
838
845
        test = Test("test_function")
839
846
        test.run(result)
840
847
        # it should invoke 'report_known_failure'.
856
863
            descriptions=0,
857
864
            verbosity=2,
858
865
            )
859
 
        _get_test("test_xfail").run(result)
860
 
        self.assertContainsRe(result_stream.getvalue(),
861
 
            "\n\\S+\\.test_xfail\\s+XFAIL\\s+\\d+ms\n"
862
 
            "\\s*(?:Text attachment: )?reason"
863
 
            "(?:\n-+\n|: {{{)"
864
 
            "this_fails"
865
 
            "(?:\n-+\n|}}}\n)")
 
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
 
872
        # can skip that.
 
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))
866
883
 
867
884
    def get_passing_test(self):
868
885
        """Return a test object that can't be run usefully."""
879
896
                self._call = test, feature
880
897
        result = InstrumentedTestResult(None, None, None, None)
881
898
        test = SampleTestCase('_test_pass')
882
 
        feature = features.Feature()
 
899
        feature = tests.Feature()
883
900
        result.startTest(test)
884
901
        result.addNotSupported(test, feature)
885
902
        # it should invoke 'report_unsupported'.
904
921
            verbosity=2,
905
922
            )
906
923
        test = self.get_passing_test()
907
 
        feature = features.Feature()
 
924
        feature = tests.Feature()
908
925
        result.startTest(test)
909
926
        prefix = len(result_stream.getvalue())
910
927
        result.report_unsupported(test, feature)
923
940
            def addNotSupported(self, test, feature):
924
941
                self._call = test, feature
925
942
        result = InstrumentedTestResult(None, None, None, None)
926
 
        feature = features.Feature()
 
943
        feature = tests.Feature()
927
944
        class Test(tests.TestCase):
928
945
            def test_function(self):
929
946
                raise tests.UnavailableFeature(feature)
948
965
    def test_strict_with_known_failure(self):
949
966
        result = bzrlib.tests.TextTestResult(self._log_file, descriptions=0,
950
967
                                             verbosity=1)
951
 
        test = _get_test("test_xfail")
952
 
        test.run(result)
 
968
        test = self.get_passing_test()
 
969
        err = (tests.KnownFailure, tests.KnownFailure('foo'), None)
 
970
        result.addExpectedFailure(test, err)
953
971
        self.assertFalse(result.wasStrictlySuccessful())
954
972
        self.assertEqual(None, result._extractBenchmarkTime(test))
955
973
 
987
1005
        self.assertEquals(2, result.count)
988
1006
 
989
1007
 
 
1008
class TestUnicodeFilenameFeature(tests.TestCase):
 
1009
 
 
1010
    def test_probe_passes(self):
 
1011
        """UnicodeFilenameFeature._probe passes."""
 
1012
        # We can't test much more than that because the behaviour depends
 
1013
        # on the platform.
 
1014
        tests.UnicodeFilenameFeature._probe()
 
1015
 
 
1016
 
990
1017
class TestRunner(tests.TestCase):
991
1018
 
992
1019
    def dummy_test(self):
1018
1045
        test = unittest.TestSuite()
1019
1046
        test.addTest(Test("known_failure_test"))
1020
1047
        def failing_test():
1021
 
            raise AssertionError('foo')
 
1048
            self.fail('foo')
1022
1049
        test.addTest(unittest.FunctionTestCase(failing_test))
1023
1050
        stream = StringIO()
1024
1051
        runner = tests.TextTestRunner(stream=stream)
1032
1059
            '^----------------------------------------------------------------------\n'
1033
1060
            'Traceback \\(most recent call last\\):\n'
1034
1061
            '  .*' # File .*, line .*, in failing_test' - but maybe not from .pyc
1035
 
            '    raise AssertionError\\(\'foo\'\\)\n'
 
1062
            '    self.fail\\(\'foo\'\\)\n'
1036
1063
            '.*'
1037
1064
            '^----------------------------------------------------------------------\n'
1038
1065
            '.*'
1044
1071
        # the final output.
1045
1072
        class Test(tests.TestCase):
1046
1073
            def known_failure_test(self):
1047
 
                self.knownFailure("Never works...")
 
1074
                self.expectFailure('failed', self.assertTrue, False)
1048
1075
        test = Test("known_failure_test")
1049
1076
        stream = StringIO()
1050
1077
        runner = tests.TextTestRunner(stream=stream)
1062
1089
                self.expectFailure("No absolute truth", self.assertTrue, True)
1063
1090
        runner = tests.TextTestRunner(stream=StringIO())
1064
1091
        result = self.run_test_runner(runner, Test("test_truth"))
1065
 
        if testtools_version <= (0, 9, 11):
1066
 
            self.assertContainsRe(runner.stream.getvalue(),
1067
 
                "=+\n"
1068
 
                "FAIL: \\S+\.test_truth\n"
1069
 
                "-+\n"
1070
 
                "(?:.*\n)*"
1071
 
                "No absolute truth\n"
1072
 
                "(?:.*\n)*"
1073
 
                "-+\n"
1074
 
                "Ran 1 test in .*\n"
1075
 
                "\n"
1076
 
                "FAILED \\(failures=1\\)\n\\Z")
1077
 
        else:
1078
 
            self.assertContainsRe(runner.stream.getvalue(),
1079
 
                "=+\n"
1080
 
                "FAIL: \\S+\.test_truth\n"
1081
 
                "-+\n"
1082
 
                "Empty attachments:\n"
1083
 
                "  log\n"
1084
 
                "\n"
1085
 
                "reason: {{{No absolute truth}}}\n"
1086
 
                "-+\n"
1087
 
                "Ran 1 test in .*\n"
1088
 
                "\n"
1089
 
                "FAILED \\(failures=1\\)\n\\Z")
 
1092
        self.assertContainsRe(runner.stream.getvalue(),
 
1093
            "=+\n"
 
1094
            "FAIL: \\S+\.test_truth\n"
 
1095
            "-+\n"
 
1096
            "(?:.*\n)*"
 
1097
            "No absolute truth\n"
 
1098
            "(?:.*\n)*"
 
1099
            "-+\n"
 
1100
            "Ran 1 test in .*\n"
 
1101
            "\n"
 
1102
            "FAILED \\(failures=1\\)\n\\Z")
1090
1103
 
1091
1104
    def test_result_decorator(self):
1092
1105
        # decorate results
1177
1190
 
1178
1191
    def test_unsupported_features_listed(self):
1179
1192
        """When unsupported features are encountered they are detailed."""
1180
 
        class Feature1(features.Feature):
 
1193
        class Feature1(tests.Feature):
1181
1194
            def _probe(self): return False
1182
 
        class Feature2(features.Feature):
 
1195
        class Feature2(tests.Feature):
1183
1196
            def _probe(self): return False
1184
1197
        # create sample tests
1185
1198
        test1 = SampleTestCase('_test_pass')
1251
1264
            lambda trace=False: "ascii")
1252
1265
        result = self.run_test_runner(tests.TextTestRunner(stream=out),
1253
1266
            FailureWithUnicode("test_log_unicode"))
1254
 
        if testtools_version > (0, 9, 11):
1255
 
            self.assertContainsRe(out.getvalue(), "log: {{{\d+\.\d+  \\\\u2606}}}")
1256
 
        else:
1257
 
            self.assertContainsRe(out.getvalue(),
1258
 
                "Text attachment: log\n"
1259
 
                "-+\n"
1260
 
                "\d+\.\d+  \\\\u2606\n"
1261
 
                "-+\n")
 
1267
        self.assertContainsRe(out.getvalue(),
 
1268
            "Text attachment: log\n"
 
1269
            "-+\n"
 
1270
            "\d+\.\d+  \\\\u2606\n"
 
1271
            "-+\n")
1262
1272
 
1263
1273
 
1264
1274
class SampleTestCase(tests.TestCase):
1465
1475
 
1466
1476
        Each self.time() call is individually and separately profiled.
1467
1477
        """
1468
 
        self.requireFeature(features.lsprof_feature)
 
1478
        self.requireFeature(test_lsprof.LSProfFeature)
1469
1479
        # overrides the class member with an instance member so no cleanup
1470
1480
        # needed.
1471
1481
        self._gather_lsprof_in_benchmarks = True
1501
1511
 
1502
1512
    def test_requireFeature_available(self):
1503
1513
        """self.requireFeature(available) is a no-op."""
1504
 
        class Available(features.Feature):
 
1514
        class Available(tests.Feature):
1505
1515
            def _probe(self):return True
1506
1516
        feature = Available()
1507
1517
        self.requireFeature(feature)
1508
1518
 
1509
1519
    def test_requireFeature_unavailable(self):
1510
1520
        """self.requireFeature(unavailable) raises UnavailableFeature."""
1511
 
        class Unavailable(features.Feature):
 
1521
        class Unavailable(tests.Feature):
1512
1522
            def _probe(self):return False
1513
1523
        feature = Unavailable()
1514
1524
        self.assertRaises(tests.UnavailableFeature,
1673
1683
        test.run(unittest.TestResult())
1674
1684
        self.assertEqual('original', obj.test_attr)
1675
1685
 
1676
 
    def test_recordCalls(self):
1677
 
        from bzrlib.tests import test_selftest
1678
 
        calls = self.recordCalls(
1679
 
            test_selftest, '_add_numbers')
1680
 
        self.assertEqual(test_selftest._add_numbers(2, 10),
1681
 
            12)
1682
 
        self.assertEquals(calls, [((2, 10), {})])
1683
 
 
1684
 
 
1685
 
def _add_numbers(a, b):
1686
 
    return a + b
1687
 
 
1688
 
 
1689
 
class _MissingFeature(features.Feature):
 
1686
 
 
1687
class _MissingFeature(tests.Feature):
1690
1688
    def _probe(self):
1691
1689
        return False
1692
1690
missing_feature = _MissingFeature()
1743
1741
        result = self._run_test('test_fail')
1744
1742
        self.assertEqual(1, len(result.failures))
1745
1743
        result_content = result.failures[0][1]
1746
 
        if testtools_version < (0, 9, 12):
1747
 
            self.assertContainsRe(result_content, 'Text attachment: log')
 
1744
        self.assertContainsRe(result_content, 'Text attachment: log')
1748
1745
        self.assertContainsRe(result_content, 'this was a failing test')
1749
1746
 
1750
1747
    def test_error_has_log(self):
1751
1748
        result = self._run_test('test_error')
1752
1749
        self.assertEqual(1, len(result.errors))
1753
1750
        result_content = result.errors[0][1]
1754
 
        if testtools_version < (0, 9, 12):
1755
 
            self.assertContainsRe(result_content, 'Text attachment: log')
 
1751
        self.assertContainsRe(result_content, 'Text attachment: log')
1756
1752
        self.assertContainsRe(result_content, 'this test errored')
1757
1753
 
1758
1754
    def test_skip_has_no_log(self):
2040
2036
        self.assertLength(2, output.readlines())
2041
2037
 
2042
2038
    def test_lsprof_tests(self):
2043
 
        self.requireFeature(features.lsprof_feature)
2044
 
        results = []
 
2039
        self.requireFeature(test_lsprof.LSProfFeature)
 
2040
        calls = []
2045
2041
        class Test(object):
2046
2042
            def __call__(test, result):
2047
2043
                test.run(result)
2048
2044
            def run(test, result):
2049
 
                results.append(result)
 
2045
                self.assertIsInstance(result, ExtendedToOriginalDecorator)
 
2046
                calls.append("called")
2050
2047
            def countTestCases(self):
2051
2048
                return 1
2052
2049
        self.run_selftest(test_suite_factory=Test, lsprof_tests=True)
2053
 
        self.assertLength(1, results)
2054
 
        self.assertIsInstance(results.pop(), ExtendedToOriginalDecorator)
 
2050
        self.assertLength(1, calls)
2055
2051
 
2056
2052
    def test_random(self):
2057
2053
        # test randomising by listing a number of tests.
2509
2505
 
2510
2506
 
2511
2507
class TestStartBzrSubProcess(tests.TestCase):
2512
 
    """Stub test start_bzr_subprocess."""
2513
2508
 
2514
 
    def _subprocess_log_cleanup(self):
2515
 
        """Inhibits the base version as we don't produce a log file."""
 
2509
    def check_popen_state(self):
 
2510
        """Replace to make assertions when popen is called."""
2516
2511
 
2517
2512
    def _popen(self, *args, **kwargs):
2518
 
        """Override the base version to record the command that is run.
2519
 
 
2520
 
        From there we can ensure it is correct without spawning a real process.
2521
 
        """
 
2513
        """Record the command that is run, so that we can ensure it is correct"""
2522
2514
        self.check_popen_state()
2523
2515
        self._popen_args = args
2524
2516
        self._popen_kwargs = kwargs
2525
2517
        raise _DontSpawnProcess()
2526
2518
 
2527
 
    def check_popen_state(self):
2528
 
        """Replace to make assertions when popen is called."""
2529
 
 
2530
2519
    def test_run_bzr_subprocess_no_plugins(self):
2531
2520
        self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [])
2532
2521
        command = self._popen_args[0]
2536
2525
 
2537
2526
    def test_allow_plugins(self):
2538
2527
        self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2539
 
                          allow_plugins=True)
 
2528
            allow_plugins=True)
2540
2529
        command = self._popen_args[0]
2541
2530
        self.assertEqual([], command[2:])
2542
2531
 
2547
2536
            self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR'])
2548
2537
        self.check_popen_state = check_environment
2549
2538
        self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2550
 
                          env_changes={'EXISTANT_ENV_VAR':'set variable'})
 
2539
            env_changes={'EXISTANT_ENV_VAR':'set variable'})
2551
2540
        # not set in theparent
2552
2541
        self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
2553
2542
 
2559
2548
        os.environ['EXISTANT_ENV_VAR'] = 'set variable'
2560
2549
        self.check_popen_state = check_environment
2561
2550
        self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2562
 
                          env_changes={'EXISTANT_ENV_VAR':None})
 
2551
            env_changes={'EXISTANT_ENV_VAR':None})
2563
2552
        # Still set in parent
2564
2553
        self.assertEqual('set variable', os.environ['EXISTANT_ENV_VAR'])
2565
2554
        del os.environ['EXISTANT_ENV_VAR']
2570
2559
            self.assertFalse('NON_EXISTANT_ENV_VAR' in os.environ)
2571
2560
        self.check_popen_state = check_environment
2572
2561
        self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2573
 
                          env_changes={'NON_EXISTANT_ENV_VAR':None})
 
2562
            env_changes={'NON_EXISTANT_ENV_VAR':None})
2574
2563
 
2575
2564
    def test_working_dir(self):
2576
2565
        """Test that we can specify the working dir for the child"""
2579
2568
        chdirs = []
2580
2569
        def chdir(path):
2581
2570
            chdirs.append(path)
2582
 
        self.overrideAttr(os, 'chdir', chdir)
2583
 
        def getcwd():
2584
 
            return 'current'
2585
 
        self.overrideAttr(osutils, 'getcwd', getcwd)
2586
 
        self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
2587
 
                          working_dir='foo')
 
2571
        os.chdir = chdir
 
2572
        try:
 
2573
            def getcwd():
 
2574
                return 'current'
 
2575
            osutils.getcwd = getcwd
 
2576
            try:
 
2577
                self.assertRaises(_DontSpawnProcess, self.start_bzr_subprocess, [],
 
2578
                    working_dir='foo')
 
2579
            finally:
 
2580
                osutils.getcwd = orig_getcwd
 
2581
        finally:
 
2582
            os.chdir = orig_chdir
2588
2583
        self.assertEqual(['foo', 'current'], chdirs)
2589
2584
 
2590
2585
    def test_get_bzr_path_with_cwd_bzrlib(self):
2610
2605
        self.assertEqual('bzr: interrupted\n', result[1])
2611
2606
 
2612
2607
 
 
2608
class TestFeature(tests.TestCase):
 
2609
 
 
2610
    def test_caching(self):
 
2611
        """Feature._probe is called by the feature at most once."""
 
2612
        class InstrumentedFeature(tests.Feature):
 
2613
            def __init__(self):
 
2614
                super(InstrumentedFeature, self).__init__()
 
2615
                self.calls = []
 
2616
            def _probe(self):
 
2617
                self.calls.append('_probe')
 
2618
                return False
 
2619
        feature = InstrumentedFeature()
 
2620
        feature.available()
 
2621
        self.assertEqual(['_probe'], feature.calls)
 
2622
        feature.available()
 
2623
        self.assertEqual(['_probe'], feature.calls)
 
2624
 
 
2625
    def test_named_str(self):
 
2626
        """Feature.__str__ should thunk to feature_name()."""
 
2627
        class NamedFeature(tests.Feature):
 
2628
            def feature_name(self):
 
2629
                return 'symlinks'
 
2630
        feature = NamedFeature()
 
2631
        self.assertEqual('symlinks', str(feature))
 
2632
 
 
2633
    def test_default_str(self):
 
2634
        """Feature.__str__ should default to __class__.__name__."""
 
2635
        class NamedFeature(tests.Feature):
 
2636
            pass
 
2637
        feature = NamedFeature()
 
2638
        self.assertEqual('NamedFeature', str(feature))
 
2639
 
 
2640
 
 
2641
class TestUnavailableFeature(tests.TestCase):
 
2642
 
 
2643
    def test_access_feature(self):
 
2644
        feature = tests.Feature()
 
2645
        exception = tests.UnavailableFeature(feature)
 
2646
        self.assertIs(feature, exception.args[0])
 
2647
 
 
2648
 
 
2649
simple_thunk_feature = tests._CompatabilityThunkFeature(
 
2650
    deprecated_in((2, 1, 0)),
 
2651
    'bzrlib.tests.test_selftest',
 
2652
    'simple_thunk_feature','UnicodeFilename',
 
2653
    replacement_module='bzrlib.tests'
 
2654
    )
 
2655
 
 
2656
class Test_CompatibilityFeature(tests.TestCase):
 
2657
 
 
2658
    def test_does_thunk(self):
 
2659
        res = self.callDeprecated(
 
2660
            ['bzrlib.tests.test_selftest.simple_thunk_feature was deprecated'
 
2661
             ' in version 2.1.0. Use bzrlib.tests.UnicodeFilename instead.'],
 
2662
            simple_thunk_feature.available)
 
2663
        self.assertEqual(tests.UnicodeFilename.available(), res)
 
2664
 
 
2665
 
 
2666
class TestModuleAvailableFeature(tests.TestCase):
 
2667
 
 
2668
    def test_available_module(self):
 
2669
        feature = tests.ModuleAvailableFeature('bzrlib.tests')
 
2670
        self.assertEqual('bzrlib.tests', feature.module_name)
 
2671
        self.assertEqual('bzrlib.tests', str(feature))
 
2672
        self.assertTrue(feature.available())
 
2673
        self.assertIs(tests, feature.module)
 
2674
 
 
2675
    def test_unavailable_module(self):
 
2676
        feature = tests.ModuleAvailableFeature('bzrlib.no_such_module_exists')
 
2677
        self.assertEqual('bzrlib.no_such_module_exists', str(feature))
 
2678
        self.assertFalse(feature.available())
 
2679
        self.assertIs(None, feature.module)
 
2680
 
 
2681
 
2613
2682
class TestSelftestFiltering(tests.TestCase):
2614
2683
 
2615
2684
    def setUp(self):
3453
3522
        self.assertDocTestStringFails(doctest.DocTestSuite, test)
3454
3523
        # tests.DocTestSuite sees None
3455
3524
        self.assertDocTestStringSucceds(tests.IsolatedDocTestSuite, test)
3456
 
 
3457
 
 
3458
 
class TestSelftestExcludePatterns(tests.TestCase):
3459
 
 
3460
 
    def setUp(self):
3461
 
        super(TestSelftestExcludePatterns, self).setUp()
3462
 
        self.overrideAttr(tests, 'test_suite', self.suite_factory)
3463
 
 
3464
 
    def suite_factory(self, keep_only=None, starting_with=None):
3465
 
        """A test suite factory with only a few tests."""
3466
 
        class Test(tests.TestCase):
3467
 
            def id(self):
3468
 
                # We don't need the full class path
3469
 
                return self._testMethodName
3470
 
            def a(self):
3471
 
                pass
3472
 
            def b(self):
3473
 
                pass
3474
 
            def c(self):
3475
 
                pass
3476
 
        return TestUtil.TestSuite([Test("a"), Test("b"), Test("c")])
3477
 
 
3478
 
    def assertTestList(self, expected, *selftest_args):
3479
 
        # We rely on setUp installing the right test suite factory so we can
3480
 
        # test at the command level without loading the whole test suite
3481
 
        out, err = self.run_bzr(('selftest', '--list') + selftest_args)
3482
 
        actual = out.splitlines()
3483
 
        self.assertEquals(expected, actual)
3484
 
 
3485
 
    def test_full_list(self):
3486
 
        self.assertTestList(['a', 'b', 'c'])
3487
 
 
3488
 
    def test_single_exclude(self):
3489
 
        self.assertTestList(['b', 'c'], '-x', 'a')
3490
 
 
3491
 
    def test_mutiple_excludes(self):
3492
 
        self.assertTestList(['c'], '-x', 'a', '-x', 'b')
3493
 
 
3494
 
 
3495
 
class TestCounterHooks(tests.TestCase, SelfTestHelper):
3496
 
 
3497
 
    _test_needs_features = [features.subunit]
3498
 
 
3499
 
    def setUp(self):
3500
 
        super(TestCounterHooks, self).setUp()
3501
 
        class Test(tests.TestCase):
3502
 
 
3503
 
            def setUp(self):
3504
 
                super(Test, self).setUp()
3505
 
                self.hooks = hooks.Hooks()
3506
 
                self.hooks.add_hook('myhook', 'Foo bar blah', (2,4))
3507
 
                self.install_counter_hook(self.hooks, 'myhook')
3508
 
 
3509
 
            def no_hook(self):
3510
 
                pass
3511
 
 
3512
 
            def run_hook_once(self):
3513
 
                for hook in self.hooks['myhook']:
3514
 
                    hook(self)
3515
 
 
3516
 
        self.test_class = Test
3517
 
 
3518
 
    def assertHookCalls(self, expected_calls, test_name):
3519
 
        test = self.test_class(test_name)
3520
 
        result = unittest.TestResult()
3521
 
        test.run(result)
3522
 
        self.assertTrue(hasattr(test, '_counters'))
3523
 
        self.assertTrue(test._counters.has_key('myhook'))
3524
 
        self.assertEquals(expected_calls, test._counters['myhook'])
3525
 
 
3526
 
    def test_no_hook(self):
3527
 
        self.assertHookCalls(0, 'no_hook')
3528
 
 
3529
 
    def test_run_hook_once(self):
3530
 
        tt = features.testtools
3531
 
        if tt.module.__version__ < (0, 9, 8):
3532
 
            raise tests.TestSkipped('testtools-0.9.8 required for addDetail')
3533
 
        self.assertHookCalls(1, 'run_hook_once')