summaryrefslogtreecommitdiff
path: root/src/mailman/testing/nose.py
blob: 6a2e0d6ba5dbc33a90fbf73c55fd35b74be0cd75 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# Copyright (C) 2013-2016 by the Free Software Foundation, Inc.
#
# This file is part of GNU Mailman.
#
# GNU Mailman is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with
# GNU Mailman.  If not, see <http://www.gnu.org/licenses/>.

"""nose2 test infrastructure."""

import os
import re
import doctest
import importlib

from mailman import public
from mailman.testing.documentation import setup, teardown
from mailman.testing.layers import ConfigLayer, MockAndMonkeyLayer, SMTPLayer
from nose2.events import Plugin
from pkg_resources import resource_filename


DOT = '.'
FLAGS = doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE | doctest.REPORT_NDIFF
TOPDIR = os.path.dirname(resource_filename('mailman', '__init__.py'))


@public
class NosePlugin(Plugin):
    configSection = 'mailman'

    def __init__(self):
        super().__init__()
        self.patterns = []
        self.stderr = False
        def set_stderr(ignore):                                  # noqa: E301
            self.stderr = True
        self.addArgument(self.patterns, 'P', 'pattern',
                         'Add a test matching pattern')
        self.addFlag(set_stderr, 'E', 'stderr',
                     'Enable stderr logging to sub-runners')

    def startTestRun(self, event):
        MockAndMonkeyLayer.testing_mode = True
        if (self.stderr or
                len(os.environ.get('MM_VERBOSE_TESTLOG', '').strip()) > 0):
            ConfigLayer.stderr = True

    def getTestCaseNames(self, event):
        if len(self.patterns) == 0:
            # No filter patterns, so everything should be tested.
            return
        # Does the pattern match the fully qualified class name?
        for pattern in self.patterns:
            full_class_name = '{}.{}'.format(
                event.testCase.__module__, event.testCase.__name__)
            if re.search(pattern, full_class_name):
                # Don't suppress this test class.
                return
        names = filter(event.isTestMethod, dir(event.testCase))
        for name in names:
            full_test_name = '{}.{}.{}'.format(
                event.testCase.__module__,
                event.testCase.__name__,
                name)
            for pattern in self.patterns:
                if re.search(pattern, full_test_name):
                    break
            else:
                event.excludedNames.append(name)

    def handleFile(self, event):
        path = event.path[len(TOPDIR)+1:]
        if len(self.patterns) > 0:
            for pattern in self.patterns:
                if re.search(pattern, path):
                    break
            else:
                # Skip this doctest.
                return
        base, ext = os.path.splitext(path)
        if ext != '.rst':
            return
        # Look to see if the package defines a test layer, otherwise use the
        # default layer.  First turn the file system path into a dotted Python
        # module path.
        parent = os.path.dirname(path)
        dotted = 'mailman.' + DOT.join(parent.split(os.path.sep))
        try:
            module = importlib.import_module(dotted)
        except ImportError:
            layer = SMTPLayer
        else:
            layer = getattr(module, 'layer', SMTPLayer)
        test = doctest.DocFileTest(
            path, package='mailman',
            optionflags=FLAGS,
            setUp=setup,
            tearDown=teardown)
        test.layer = layer
        # Suppress the extra "Doctest: ..." line.
        test.shortDescription = lambda: None
        event.extraTests.append(test)

    # def startTest(self, event):
    #     import sys; print('vvvvv', event.test, file=sys.stderr)

    # def stopTest(self, event):
    #     import sys; print('^^^^^', event.test, file=sys.stderr)