comparison MoinMoin/_tests/__init__.py @ 0:77665d8e2254

tag of nonpublic@localhost--archive/moin--enterprise--1.5--base-0 (automatically generated log message) imported from: moin--main--1.5--base-0
author Thomas Waldmann <tw-public@gmx.de>
date Thu, 22 Sep 2005 15:09:50 +0000
parents
children df348d27f1fc
comparison
equal deleted inserted replaced
-1:000000000000 0:77665d8e2254
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_pakcage_module.
9
10 Each test_ module may contain test case classes sub classed from
11 unittest.TestCase or subclass of it. Previous versions required TestCase
12 suffix, but now its only a convention.
13
14 Each test case class may contain multiply test methods, that must start
15 with 'test'. Those methods will be run by the test suites.
16
17 Test that need the current request, for example to create a page
18 instance, can refer to self.request. It is injected into all test case
19 classes by the framework.
20
21 Tests that require certain configuration, like section_numbers = 1, must
22 use a TestConfig to create the required configuration before the
23 test. Deleting the TestConfig instance will restore the previous
24 configuration.
25
26 See _test_template.py for an example, and use it to create new tests.
27
28 Typical Usage
29 -------------
30
31 Running all test in this package::
32
33 from MoinMoin._tests import run
34 run(request)
35
36 Running only few modules::
37
38 run(request, names=['test_this', 'test_that'])
39
40 @copyright: 2002-2004 by Jürgen Hermann <jh@web.de>
41 @license: GNU GPL, see COPYING for details.
42 """
43
44 from unittest import TestLoader, TextTestRunner
45
46
47 class TestSkiped(Exception):
48 """ Raised when a tests is skipped """
49
50
51 class TestConfig:
52 """ Custom configuration for unit tests
53
54 Some test assume specific configuration, and will fail if the wiki admin
55 will change the configuration. For example, DateTime macro test assume
56 the default datetime_fmt.
57
58 When you set custom values in a TestConfig, the previous values are saved,
59 and when the TestConfig is deleted, they are restored automatically.
60
61 Typical Usage
62 ------------
63 ::
64 from MoinMoin._tests import TestConfig
65 class SomeTestCase(unittest.TestCase):
66 def setUp(self):
67 self.config = TestConfig(self.request,
68 defaults=key_list, key=value,...)
69 def tearDown(self):
70 del self.config
71 def testSomething(self):
72 # test that needs those defaults and custom values
73 """
74
75 def __init__(self, request, defaults=(), **custom):
76 """ Create temporary configuration for a test
77
78 @param request: current request
79 @param defaults: list of keys that should use the default value
80 @param **custom: other keys using non default values, or new keys
81 that request.cfg does not have already
82 """
83 self.request = request
84 self.old = {} # Old config values
85 self.new = [] # New added attributes
86 self.setDefaults(defaults)
87 self.setCustom(**custom)
88
89 def setDefaults(self, defaults=()):
90 """ Set default values for keys in defaults list
91
92 Non existing default will raise an AttributeError.
93 """
94 from MoinMoin.multiconfig import DefaultConfig
95 for key in defaults:
96 self._setattr(key, getattr(DefaultConfig, key))
97
98 def setCustom(self, **custom):
99 """ Set custom values """
100 for key, value in custom.items():
101 self._setattr(key, value)
102
103 def _setattr(self, key, value):
104 """ Set a new value for key saving new added keys """
105 if hasattr(self.request.cfg, key):
106 self.old[key] = getattr(self.request.cfg, key)
107 else:
108 self.new.append(key)
109 setattr(self.request.cfg, key, value)
110
111 def __del__(self):
112 """ Restore previous request.cfg
113
114 Set old keys to old values and delete new keys.
115 """
116 for key, value in self.old.items():
117 setattr(self.request.cfg, key, value)
118 for key in self.new:
119 delattr(self.request.cfg, key)
120
121
122 class MoinTestLoader(TestLoader):
123 """ Customized test loader that support long running process
124
125 To enable testing long running process, we inject the current
126 request into each test case class. Later, each test can refer to
127 request as self.request.
128 """
129 def __init__(self, request):
130 self.request = request
131
132 def loadTestsFromTestCase(self, testCaseClass):
133 testCaseClass.request = self.request
134 return TestLoader.loadTestsFromTestCase(self, testCaseClass)
135
136
137 def makeSuite(request, names=None):
138 """ Create test suites from modules in names
139
140 @param request: current request
141 @param names: module names to get tests from. If the list is empty,
142 all test modules in the _tests package are used.
143 @rtype: C{unittest.TestSuite}
144 @return: test suite with all test cases in names
145 """
146 if not names:
147 from MoinMoin.util.pysupport import getPackageModules
148 names = getPackageModules(__file__)
149 names = ['%s.%s' % (__name__, name) for name in names
150 if name.startswith('test_')]
151 caseInsensitiveCompare = lambda a, b: cmp(a.lower(), b.lower())
152 names.sort(caseInsensitiveCompare)
153 loader = MoinTestLoader(request)
154 return loader.loadTestsFromNames(names)
155
156
157 def run(request=None, names=None):
158 """ Run test suit
159
160 @param request: current request
161 @param names: list fully qualified module names to test,
162 e.g MoinMoin._tests.test_error
163 """
164 if request is None:
165 from MoinMoin.request import RequestCLI
166 from MoinMoin.user import User
167 request = RequestCLI()
168 request.form = request.args = request.setup_args()
169 request.user = User(request)
170
171 suite = makeSuite(request, names)
172 TextTestRunner(stream=request, verbosity=2).run(suite)