OLD | NEW |
| (Empty) |
1 # Copyright (c) 2001-2007 Twisted Matrix Laboratories. | |
2 # See LICENSE for details. | |
3 | |
4 import gc | |
5 import StringIO, sys, types | |
6 | |
7 from twisted.trial import unittest, runner | |
8 from twisted.scripts import trial | |
9 from twisted.python import util | |
10 from twisted.python.compat import set | |
11 | |
12 from twisted.trial.test.test_loader import testNames | |
13 | |
14 pyunit = __import__('unittest') | |
15 | |
16 | |
17 def sibpath(filename): | |
18 """For finding files in twisted/trial/test""" | |
19 return util.sibpath(__file__, filename) | |
20 | |
21 | |
22 | |
23 class ForceGarbageCollection(unittest.TestCase): | |
24 """ | |
25 Tests for the --force-gc option. | |
26 """ | |
27 | |
28 def setUp(self): | |
29 self.config = trial.Options() | |
30 self.log = [] | |
31 self.patch(gc, 'collect', self.collect) | |
32 test = pyunit.FunctionTestCase(self.simpleTest) | |
33 self.test = runner.TestSuite([test, test]) | |
34 | |
35 | |
36 def simpleTest(self): | |
37 """ | |
38 A simple test method that records that it was run. | |
39 """ | |
40 self.log.append('test') | |
41 | |
42 | |
43 def collect(self): | |
44 """ | |
45 A replacement for gc.collect that logs calls to itself. | |
46 """ | |
47 self.log.append('collect') | |
48 | |
49 | |
50 def makeRunner(self): | |
51 """ | |
52 Return a L{runner.TrialRunner} object that is safe to use in tests. | |
53 """ | |
54 runner = trial._makeRunner(self.config) | |
55 runner.stream = StringIO.StringIO() | |
56 return runner | |
57 | |
58 | |
59 def test_forceGc(self): | |
60 """ | |
61 Passing the --force-gc option to the trial script forces the garbage | |
62 collector to run before and after each test. | |
63 """ | |
64 self.config['force-gc'] = True | |
65 self.config.postOptions() | |
66 runner = self.makeRunner() | |
67 runner.run(self.test) | |
68 self.assertEqual(self.log, ['collect', 'test', 'collect', | |
69 'collect', 'test', 'collect']) | |
70 | |
71 | |
72 def test_unforceGc(self): | |
73 """ | |
74 By default, no garbage collection is forced. | |
75 """ | |
76 self.config.postOptions() | |
77 runner = self.makeRunner() | |
78 runner.run(self.test) | |
79 self.assertEqual(self.log, ['test', 'test']) | |
80 | |
81 | |
82 | |
83 class TestSuiteUsed(unittest.TestCase): | |
84 """ | |
85 Check the category of tests suite used by the loader. | |
86 """ | |
87 | |
88 def setUp(self): | |
89 """ | |
90 Create a trial configuration object. | |
91 """ | |
92 self.config = trial.Options() | |
93 | |
94 | |
95 def test_defaultSuite(self): | |
96 """ | |
97 By default, the loader should use L{runner.DestructiveTestSuite} | |
98 """ | |
99 loader = trial._getLoader(self.config) | |
100 self.assertEquals(loader.suiteFactory, runner.DestructiveTestSuite) | |
101 | |
102 | |
103 def test_untilFailureSuite(self): | |
104 """ | |
105 The C{until-failure} configuration uses the L{runner.TestSuite} to keep | |
106 instances alive across runs. | |
107 """ | |
108 self.config['until-failure'] = True | |
109 loader = trial._getLoader(self.config) | |
110 self.assertEquals(loader.suiteFactory, runner.TestSuite) | |
111 | |
112 | |
113 | |
114 class TestModuleTest(unittest.TestCase): | |
115 def setUp(self): | |
116 self.config = trial.Options() | |
117 | |
118 def tearDown(self): | |
119 self.config = None | |
120 | |
121 def test_testNames(self): | |
122 """ | |
123 Check that the testNames helper method accurately collects the | |
124 names of tests in suite. | |
125 """ | |
126 self.assertEqual(testNames(self), [self.id()]) | |
127 | |
128 def assertSuitesEqual(self, test1, names): | |
129 loader = runner.TestLoader() | |
130 names1 = testNames(test1) | |
131 names2 = testNames(runner.TestSuite(map(loader.loadByName, names))) | |
132 names1.sort() | |
133 names2.sort() | |
134 self.assertEqual(names1, names2) | |
135 | |
136 def test_baseState(self): | |
137 self.failUnlessEqual(0, len(self.config['tests'])) | |
138 | |
139 def test_testmoduleOnModule(self): | |
140 """ | |
141 Check that --testmodule loads a suite which contains the tests | |
142 referred to in test-case-name inside its parameter. | |
143 """ | |
144 self.config.opt_testmodule(sibpath('moduletest.py')) | |
145 self.assertSuitesEqual(trial._getSuite(self.config), | |
146 ['twisted.trial.test.test_test_visitor']) | |
147 | |
148 def test_testmoduleTwice(self): | |
149 """ | |
150 When the same module is specified with two --testmodule flags, it | |
151 should only appear once in the suite. | |
152 """ | |
153 self.config.opt_testmodule(sibpath('moduletest.py')) | |
154 self.config.opt_testmodule(sibpath('moduletest.py')) | |
155 self.assertSuitesEqual(trial._getSuite(self.config), | |
156 ['twisted.trial.test.test_test_visitor']) | |
157 | |
158 def test_testmoduleOnSourceAndTarget(self): | |
159 """ | |
160 If --testmodule is specified twice, once for module A and once for | |
161 a module which refers to module A, then make sure module A is only | |
162 added once. | |
163 """ | |
164 self.config.opt_testmodule(sibpath('moduletest.py')) | |
165 self.config.opt_testmodule(sibpath('test_test_visitor.py')) | |
166 self.assertSuitesEqual(trial._getSuite(self.config), | |
167 ['twisted.trial.test.test_test_visitor']) | |
168 | |
169 def test_testmoduleOnSelfModule(self): | |
170 """ | |
171 When given a module that refers to *itself* in the test-case-name | |
172 variable, check that --testmodule only adds the tests once. | |
173 """ | |
174 self.config.opt_testmodule(sibpath('moduleself.py')) | |
175 self.assertSuitesEqual(trial._getSuite(self.config), | |
176 ['twisted.trial.test.moduleself']) | |
177 | |
178 def test_testmoduleOnScript(self): | |
179 """ | |
180 Check that --testmodule loads tests referred to in test-case-name | |
181 buffer variables. | |
182 """ | |
183 self.config.opt_testmodule(sibpath('scripttest.py')) | |
184 self.assertSuitesEqual(trial._getSuite(self.config), | |
185 ['twisted.trial.test.test_test_visitor', | |
186 'twisted.trial.test.test_class']) | |
187 | |
188 def test_testmoduleOnNonexistentFile(self): | |
189 """ | |
190 Check that --testmodule displays a meaningful error message when | |
191 passed a non-existent filename. | |
192 """ | |
193 buffy = StringIO.StringIO() | |
194 stderr, sys.stderr = sys.stderr, buffy | |
195 filename = 'test_thisbetternoteverexist.py' | |
196 try: | |
197 self.config.opt_testmodule(filename) | |
198 self.failUnlessEqual(0, len(self.config['tests'])) | |
199 self.failUnlessEqual("File %r doesn't exist\n" % (filename,), | |
200 buffy.getvalue()) | |
201 finally: | |
202 sys.stderr = stderr | |
203 | |
204 def test_testmoduleOnEmptyVars(self): | |
205 """ | |
206 Check that --testmodule adds no tests to the suite for modules | |
207 which lack test-case-name buffer variables. | |
208 """ | |
209 self.config.opt_testmodule(sibpath('novars.py')) | |
210 self.failUnlessEqual(0, len(self.config['tests'])) | |
211 | |
212 def test_testmoduleOnModuleName(self): | |
213 """ | |
214 Check that --testmodule does *not* support module names as arguments | |
215 and that it displays a meaningful error message. | |
216 """ | |
217 buffy = StringIO.StringIO() | |
218 stderr, sys.stderr = sys.stderr, buffy | |
219 moduleName = 'twisted.trial.test.test_script' | |
220 try: | |
221 self.config.opt_testmodule(moduleName) | |
222 self.failUnlessEqual(0, len(self.config['tests'])) | |
223 self.failUnlessEqual("File %r doesn't exist\n" % (moduleName,), | |
224 buffy.getvalue()) | |
225 finally: | |
226 sys.stderr = stderr | |
227 | |
228 def test_parseLocalVariable(self): | |
229 declaration = '-*- test-case-name: twisted.trial.test.test_tests -*-' | |
230 localVars = trial._parseLocalVariables(declaration) | |
231 self.failUnlessEqual({'test-case-name': | |
232 'twisted.trial.test.test_tests'}, | |
233 localVars) | |
234 | |
235 def test_trailingSemicolon(self): | |
236 declaration = '-*- test-case-name: twisted.trial.test.test_tests; -*-' | |
237 localVars = trial._parseLocalVariables(declaration) | |
238 self.failUnlessEqual({'test-case-name': | |
239 'twisted.trial.test.test_tests'}, | |
240 localVars) | |
241 | |
242 def test_parseLocalVariables(self): | |
243 declaration = ('-*- test-case-name: twisted.trial.test.test_tests; ' | |
244 'foo: bar -*-') | |
245 localVars = trial._parseLocalVariables(declaration) | |
246 self.failUnlessEqual({'test-case-name': | |
247 'twisted.trial.test.test_tests', | |
248 'foo': 'bar'}, | |
249 localVars) | |
250 | |
251 def test_surroundingGuff(self): | |
252 declaration = ('## -*- test-case-name: ' | |
253 'twisted.trial.test.test_tests -*- #') | |
254 localVars = trial._parseLocalVariables(declaration) | |
255 self.failUnlessEqual({'test-case-name': | |
256 'twisted.trial.test.test_tests'}, | |
257 localVars) | |
258 | |
259 def test_invalidLine(self): | |
260 self.failUnlessRaises(ValueError, trial._parseLocalVariables, | |
261 'foo') | |
262 | |
263 def test_invalidDeclaration(self): | |
264 self.failUnlessRaises(ValueError, trial._parseLocalVariables, | |
265 '-*- foo -*-') | |
266 self.failUnlessRaises(ValueError, trial._parseLocalVariables, | |
267 '-*- foo: bar; qux -*-') | |
268 self.failUnlessRaises(ValueError, trial._parseLocalVariables, | |
269 '-*- foo: bar: baz; qux: qax -*-') | |
270 | |
271 def test_variablesFromFile(self): | |
272 localVars = trial.loadLocalVariables(sibpath('moduletest.py')) | |
273 self.failUnlessEqual({'test-case-name': | |
274 'twisted.trial.test.test_test_visitor'}, | |
275 localVars) | |
276 | |
277 def test_noVariablesInFile(self): | |
278 localVars = trial.loadLocalVariables(sibpath('novars.py')) | |
279 self.failUnlessEqual({}, localVars) | |
280 | |
281 def test_variablesFromScript(self): | |
282 localVars = trial.loadLocalVariables(sibpath('scripttest.py')) | |
283 self.failUnlessEqual( | |
284 {'test-case-name': ('twisted.trial.test.test_test_visitor,' | |
285 'twisted.trial.test.test_class')}, | |
286 localVars) | |
287 | |
288 def test_getTestModules(self): | |
289 modules = trial.getTestModules(sibpath('moduletest.py')) | |
290 self.failUnlessEqual(modules, ['twisted.trial.test.test_test_visitor']) | |
291 | |
292 def test_getTestModules_noVars(self): | |
293 modules = trial.getTestModules(sibpath('novars.py')) | |
294 self.failUnlessEqual(len(modules), 0) | |
295 | |
296 def test_getTestModules_multiple(self): | |
297 modules = trial.getTestModules(sibpath('scripttest.py')) | |
298 self.failUnlessEqual(set(modules), | |
299 set(['twisted.trial.test.test_test_visitor', | |
300 'twisted.trial.test.test_class'])) | |
301 | |
302 def test_looksLikeTestModule(self): | |
303 for filename in ['test_script.py', 'twisted/trial/test/test_script.py']: | |
304 self.failUnless(trial.isTestFile(filename), | |
305 "%r should be a test file" % (filename,)) | |
306 for filename in ['twisted/trial/test/moduletest.py', | |
307 sibpath('scripttest.py'), sibpath('test_foo.bat')]: | |
308 self.failIf(trial.isTestFile(filename), | |
309 "%r should *not* be a test file" % (filename,)) | |
310 | |
311 | |
312 class WithoutModuleTests(unittest.TestCase): | |
313 """ | |
314 Test the C{without-module} flag. | |
315 """ | |
316 | |
317 def setUp(self): | |
318 """ | |
319 Create a L{trial.Options} object to be used in the tests, and save | |
320 C{sys.modules}. | |
321 """ | |
322 self.config = trial.Options() | |
323 self.savedModules = dict(sys.modules) | |
324 | |
325 | |
326 def tearDown(self): | |
327 """ | |
328 Restore C{sys.modules}. | |
329 """ | |
330 for module in ('imaplib', 'smtplib'): | |
331 if module in self.savedModules: | |
332 sys.modules[module] = self.savedModules[module] | |
333 else: | |
334 sys.modules.pop(module, None) | |
335 | |
336 | |
337 def _checkSMTP(self): | |
338 """ | |
339 Try to import the C{smtplib} module, and return it. | |
340 """ | |
341 import smtplib | |
342 return smtplib | |
343 | |
344 | |
345 def _checkIMAP(self): | |
346 """ | |
347 Try to import the C{imaplib} module, and return it. | |
348 """ | |
349 import imaplib | |
350 return imaplib | |
351 | |
352 | |
353 def test_disableOneModule(self): | |
354 """ | |
355 Check that after disabling a module, it can't be imported anymore. | |
356 """ | |
357 self.config.parseOptions(["--without-module", "smtplib"]) | |
358 self.assertRaises(ImportError, self._checkSMTP) | |
359 # Restore sys.modules | |
360 del sys.modules["smtplib"] | |
361 # Then the function should succeed | |
362 self.assertIsInstance(self._checkSMTP(), types.ModuleType) | |
363 | |
364 | |
365 def test_disableMultipleModules(self): | |
366 """ | |
367 Check that several modules can be disabled at once. | |
368 """ | |
369 self.config.parseOptions(["--without-module", "smtplib,imaplib"]) | |
370 self.assertRaises(ImportError, self._checkSMTP) | |
371 self.assertRaises(ImportError, self._checkIMAP) | |
372 # Restore sys.modules | |
373 del sys.modules["smtplib"] | |
374 del sys.modules["imaplib"] | |
375 # Then the functions should succeed | |
376 self.assertIsInstance(self._checkSMTP(), types.ModuleType) | |
377 self.assertIsInstance(self._checkIMAP(), types.ModuleType) | |
378 | |
379 | |
380 def test_disableAlreadyImportedModule(self): | |
381 """ | |
382 Disabling an already imported module should produce a warning. | |
383 """ | |
384 self.assertIsInstance(self._checkSMTP(), types.ModuleType) | |
385 self.assertWarns(RuntimeWarning, | |
386 "Module 'smtplib' already imported, disabling anyway.", | |
387 trial.__file__, | |
388 self.config.parseOptions, ["--without-module", "smtplib"]) | |
389 self.assertRaises(ImportError, self._checkSMTP) | |
390 | |
OLD | NEW |