comparison MoinMoin/conftest.py @ 2006:1339d6fdc4ff

Changed tests to use py.test. Also changed the semantics a bit - the test wiki directory is only created freshly if it does not exist.
author Alexander Schremmer <alex AT alexanderweb DOT de>
date Fri, 20 Apr 2007 00:12:50 +0200
parents
children c4cbabe9a02d
comparison
equal deleted inserted replaced
2005:511924c36086 2006:1339d6fdc4ff
1 # -*- coding: iso-8859-1 -*-
2 """
3 MoinMoin Testing Framework
4 --------------------------
5
6 All test modules must be named test_modulename to be included in the
7 test suit. If you are testing a package, name the test module
8 test_package_module.
9
10 Tests that need the current request, for example to create a page
11 instance, can refer to self.request. It is injected into all test case
12 classes by the framework.
13
14 Tests that require certain configuration, like section_numbers = 1, must
15 use a TestConfig to create the required configuration before the
16 test. Deleting the TestConfig instance will restore the previous
17 configuration.
18
19 @copyright: 2005 Nir Soffer, 2007 Alexander Schremmer
20 @license: GNU GPL, see COPYING for details.
21 """
22
23 import atexit
24 from inspect import isclass
25 from sys import modules
26 import sys
27
28 import py
29
30
31 rootdir = py.magic.autopath().dirpath()
32 moindir = rootdir.join("..")
33
34 sys.path.insert(0, str(moindir))
35 from MoinMoin._tests import maketestwiki, compat
36 modules["unittest"] = compat # evil hack
37
38 sys.path.insert(0, str(moindir.join("tests")))
39
40
41 coverage_modules = set()
42
43
44 try:
45 """
46 This code adds support for coverage.py (see
47 http://nedbatchelder.com/code/modules/coverage.html).
48 It prints a coverage report for the modules specified in all
49 module globals (of the test modules) named "coverage_modules".
50 """
51
52 import coverage
53
54 def report_coverage():
55 coverage.stop()
56 module_list = [modules[mod] for mod in coverage_modules]
57 module_list.sort()
58 coverage.report(module_list)
59
60 def callback(option, opt_str, value, parser):
61 atexit.register(report_coverage)
62 coverage.erase()
63 coverage.start()
64
65
66 py.test.config.addoptions('MoinMoin options', py.test.config.Option('-C',
67 '--coverage', action='callback', callback=callback,
68 help='Output information about code coverage (slow!)'))
69
70 except ImportError:
71 coverage = None
72
73
74 def init_test_request(static_state=[False]):
75 from MoinMoin.request import CLI
76 from MoinMoin.user import User
77 if not static_state[0]:
78 maketestwiki.run(True)
79 static_state[0] = True
80 request = CLI.Request()
81 request.form = request.args = request.setup_args()
82 request.user = User(request)
83 return request
84
85
86 class TestConfig:
87 """ Custom configuration for unit tests
88
89 Some test assume specific configuration, and will fail if the wiki admin
90 will change the configuration. For example, DateTime macro test assume
91 the default datetime_fmt.
92
93 When you set custom values in a TestConfig, the previous values are saved,
94 and when the TestConfig is called specifically, they are restored automatically.
95
96 Typical Usage
97 -------------
98 ::
99 class SomeTest:
100 def setUp(self):
101 self.config = self.TestConfig(defaults=key_list, key=value,...)
102 def tearDown(self):
103 self.config.restore()
104 def testSomething(self):
105 # test that needs those defaults and custom values
106 """
107
108 def __init__(self, request):
109 """ Create temporary configuration for a test
110
111 @param request: current request
112 """
113 self.request = request
114 self.old = {} # Old config values
115 self.new = [] # New added attributes
116
117 def __call__(self, defaults=(), **custom):
118 """ Initialise a temporary configuration for a test
119
120 @param defaults: list of keys that should use the default value
121 @param custom: other keys using non default values, or new keys
122 that request.cfg does not have already
123 """
124 self.setDefaults(defaults)
125 self.setCustom(**custom)
126
127 return self
128
129 def setDefaults(self, defaults=()):
130 """ Set default values for keys in defaults list
131
132 Non existing default will raise an AttributeError.
133 """
134 from MoinMoin.config import multiconfig
135 for key in defaults:
136 self._setattr(key, getattr(multiconfig.DefaultConfig, key))
137
138 def setCustom(self, **custom):
139 """ Set custom values """
140 for key, value in custom.items():
141 self._setattr(key, value)
142
143 def _setattr(self, key, value):
144 """ Set a new value for key saving new added keys """
145 if hasattr(self.request.cfg, key):
146 self.old[key] = getattr(self.request.cfg, key)
147 else:
148 self.new.append(key)
149 setattr(self.request.cfg, key, value)
150
151 def restore(self):
152 """ Restore previous request.cfg
153
154 Set old keys to old values and delete new keys.
155 """
156 for key, value in self.old.items():
157 setattr(self.request.cfg, key, value)
158 for key in self.new:
159 delattr(self.request.cfg, key)
160
161
162 class Module(py.test.collect.Module):
163 def __init__(self, *args, **kwargs):
164 self.request = init_test_request()
165 super(Module, self).__init__(*args, **kwargs)
166
167 def run(self, *args, **kwargs):
168 if coverage is not None:
169 coverage_modules.update(getattr(self.obj, 'coverage_modules', []))
170 return super(Module, self).run(*args, **kwargs)
171
172 def join(self, name):
173 obj = getattr(self.obj, name)
174 if isclass(obj):
175 return MoinClassCollector(name, parent=self)
176 elif hasattr(obj, 'func_code'):
177 return MoinTestFunction(name, parent=self)
178
179
180 class MoinTestFunction(py.test.collect.Function):
181 def execute(self, target, *args):
182 request = self.parent.request
183 co = target.func_code
184 if 'request' in co.co_varnames[:co.co_argcount]:
185 target(request, *args)
186 else:
187 target(*args)
188
189
190 class MoinClassCollector(py.test.collect.Class):
191 Function = MoinTestFunction
192
193 def setup(self):
194 cls = self.obj
195 cls.request = self.parent.request
196 cls.TestConfig = TestConfig(cls.request)
197 super(MoinClassCollector, self).setup()