~justin-fathomdb/nova/justinsb-openstack-api-volumes

« back to all changes in this revision

Viewing changes to vendor/Twisted-10.0.0/twisted/trial/test/test_loader.py

  • Committer: Jesse Andrews
  • Date: 2010-05-28 06:05:26 UTC
  • Revision ID: git-v1:bf6e6e718cdc7488e2da87b21e258ccc065fe499
initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (c) 2008-2009 Twisted Matrix Laboratories.
 
2
# See LICENSE for details.
 
3
 
 
4
"""
 
5
Tests for loading tests by name.
 
6
"""
 
7
 
 
8
import os
 
9
import shutil
 
10
import sys
 
11
 
 
12
from twisted.python import util
 
13
from twisted.python.hashlib import md5
 
14
from twisted.trial.test import packages
 
15
from twisted.trial import runner, reporter, unittest
 
16
from twisted.trial.itrial import ITestCase
 
17
 
 
18
from twisted.python.modules import getModule
 
19
 
 
20
 
 
21
 
 
22
def testNames(tests):
 
23
    """
 
24
    Return the id of each test within the given test suite or case.
 
25
    """
 
26
    names = []
 
27
    for test in unittest._iterateTests(tests):
 
28
        names.append(test.id())
 
29
    return names
 
30
 
 
31
 
 
32
 
 
33
class FinderTest(packages.PackageTest):
 
34
    def setUp(self):
 
35
        packages.PackageTest.setUp(self)
 
36
        self.loader = runner.TestLoader()
 
37
 
 
38
    def tearDown(self):
 
39
        packages.PackageTest.tearDown(self)
 
40
 
 
41
    def test_findPackage(self):
 
42
        sample1 = self.loader.findByName('twisted')
 
43
        import twisted as sample2
 
44
        self.failUnlessEqual(sample1, sample2)
 
45
 
 
46
    def test_findModule(self):
 
47
        sample1 = self.loader.findByName('twisted.trial.test.sample')
 
48
        import sample as sample2
 
49
        self.failUnlessEqual(sample1, sample2)
 
50
 
 
51
    def test_findFile(self):
 
52
        path = util.sibpath(__file__, 'sample.py')
 
53
        sample1 = self.loader.findByName(path)
 
54
        import sample as sample2
 
55
        self.failUnlessEqual(sample1, sample2)
 
56
 
 
57
    def test_findObject(self):
 
58
        sample1 = self.loader.findByName('twisted.trial.test.sample.FooTest')
 
59
        import sample
 
60
        self.failUnlessEqual(sample.FooTest, sample1)
 
61
 
 
62
    def test_findNonModule(self):
 
63
        self.failUnlessRaises(AttributeError,
 
64
                              self.loader.findByName,
 
65
                              'twisted.trial.test.nonexistent')
 
66
 
 
67
    def test_findNonPackage(self):
 
68
        self.failUnlessRaises(ValueError,
 
69
                              self.loader.findByName,
 
70
                              'nonextant')
 
71
 
 
72
    def test_findNonFile(self):
 
73
        path = util.sibpath(__file__, 'nonexistent.py')
 
74
        self.failUnlessRaises(ValueError, self.loader.findByName, path)
 
75
 
 
76
 
 
77
 
 
78
class FileTest(packages.SysPathManglingTest):
 
79
    """
 
80
    Tests for L{runner.filenameToModule}.
 
81
    """
 
82
    def test_notFile(self):
 
83
        self.failUnlessRaises(ValueError,
 
84
                              runner.filenameToModule, 'doesntexist')
 
85
 
 
86
    def test_moduleInPath(self):
 
87
        sample1 = runner.filenameToModule(util.sibpath(__file__, 'sample.py'))
 
88
        import sample as sample2
 
89
        self.failUnlessEqual(sample2, sample1)
 
90
 
 
91
 
 
92
    def test_moduleNotInPath(self):
 
93
        """
 
94
        If passed the path to a file containing the implementation of a
 
95
        module within a package which is not on the import path,
 
96
        L{runner.filenameToModule} returns a module object loosely
 
97
        resembling the module defined by that file anyway.
 
98
        """
 
99
        # "test_sample" isn't actually the name of this module.  However,
 
100
        # filenameToModule can't seem to figure that out.  So clean up this
 
101
        # mis-named module.  It would be better if this weren't necessary
 
102
        # and filenameToModule either didn't exist or added a correctly
 
103
        # named module to sys.modules.
 
104
        self.addCleanup(sys.modules.pop, 'test_sample', None)
 
105
 
 
106
        self.mangleSysPath(self.oldPath)
 
107
        sample1 = runner.filenameToModule(
 
108
            os.path.join(self.parent, 'goodpackage', 'test_sample.py'))
 
109
        self.mangleSysPath(self.newPath)
 
110
        from goodpackage import test_sample as sample2
 
111
        self.failUnlessEqual(os.path.splitext(sample2.__file__)[0],
 
112
                             os.path.splitext(sample1.__file__)[0])
 
113
 
 
114
 
 
115
    def test_packageInPath(self):
 
116
        package1 = runner.filenameToModule(os.path.join(self.parent,
 
117
                                                        'goodpackage'))
 
118
        import goodpackage
 
119
        self.failUnlessEqual(goodpackage, package1)
 
120
 
 
121
 
 
122
    def test_packageNotInPath(self):
 
123
        """
 
124
        If passed the path to a directory which represents a package which
 
125
        is not on the import path, L{runner.filenameToModule} returns a
 
126
        module object loosely resembling the package defined by that
 
127
        directory anyway.
 
128
        """
 
129
        # "__init__" isn't actually the name of the package!  However,
 
130
        # filenameToModule is pretty stupid and decides that is its name
 
131
        # after all.  Make sure it gets cleaned up.  See the comment in
 
132
        # test_moduleNotInPath for possible courses of action related to
 
133
        # this.
 
134
        self.addCleanup(sys.modules.pop, "__init__")
 
135
 
 
136
        self.mangleSysPath(self.oldPath)
 
137
        package1 = runner.filenameToModule(
 
138
            os.path.join(self.parent, 'goodpackage'))
 
139
        self.mangleSysPath(self.newPath)
 
140
        import goodpackage
 
141
        self.failUnlessEqual(os.path.splitext(goodpackage.__file__)[0],
 
142
                             os.path.splitext(package1.__file__)[0])
 
143
 
 
144
 
 
145
    def test_directoryNotPackage(self):
 
146
        self.failUnlessRaises(ValueError, runner.filenameToModule,
 
147
                              util.sibpath(__file__, 'directory'))
 
148
 
 
149
    def test_filenameNotPython(self):
 
150
        self.failUnlessRaises(ValueError, runner.filenameToModule,
 
151
                              util.sibpath(__file__, 'notpython.py'))
 
152
 
 
153
    def test_filenameMatchesPackage(self):
 
154
        filename = os.path.join(self.parent, 'goodpackage.py')
 
155
        fd = open(filename, 'w')
 
156
        fd.write(packages.testModule)
 
157
        fd.close()
 
158
        try:
 
159
            module = runner.filenameToModule(filename)
 
160
            self.failUnlessEqual(filename, module.__file__)
 
161
        finally:
 
162
            os.remove(filename)
 
163
 
 
164
    def test_directory(self):
 
165
        """
 
166
        Test loader against a filesystem directory. It should handle
 
167
        'path' and 'path/' the same way.
 
168
        """
 
169
        path  = util.sibpath(__file__, 'goodDirectory')
 
170
        os.mkdir(path)
 
171
        f = file(os.path.join(path, '__init__.py'), "w")
 
172
        f.close()
 
173
        try:
 
174
            module = runner.filenameToModule(path)
 
175
            self.assert_(module.__name__.endswith('goodDirectory'))
 
176
            module = runner.filenameToModule(path + os.path.sep)
 
177
            self.assert_(module.__name__.endswith('goodDirectory'))
 
178
        finally:
 
179
            shutil.rmtree(path)
 
180
 
 
181
 
 
182
 
 
183
class LoaderTest(packages.SysPathManglingTest):
 
184
 
 
185
    def setUp(self):
 
186
        self.loader = runner.TestLoader()
 
187
        packages.SysPathManglingTest.setUp(self)
 
188
 
 
189
    def test_sortCases(self):
 
190
        import sample
 
191
        suite = self.loader.loadClass(sample.AlphabetTest)
 
192
        self.failUnlessEqual(['test_a', 'test_b', 'test_c'],
 
193
                             [test._testMethodName for test in suite._tests])
 
194
        newOrder = ['test_b', 'test_c', 'test_a']
 
195
        sortDict = dict(zip(newOrder, range(3)))
 
196
        self.loader.sorter = lambda x : sortDict.get(x.shortDescription(), -1)
 
197
        suite = self.loader.loadClass(sample.AlphabetTest)
 
198
        self.failUnlessEqual(newOrder,
 
199
                             [test._testMethodName for test in suite._tests])
 
200
 
 
201
    def test_loadMethod(self):
 
202
        import sample
 
203
        suite = self.loader.loadMethod(sample.FooTest.test_foo)
 
204
        self.failUnlessEqual(1, suite.countTestCases())
 
205
        self.failUnlessEqual('test_foo', suite._testMethodName)
 
206
 
 
207
    def test_loadFailingMethod(self):
 
208
        # test added for issue1353
 
209
        import erroneous
 
210
        suite = self.loader.loadMethod(erroneous.TestRegularFail.test_fail)
 
211
        result = reporter.TestResult()
 
212
        suite.run(result)
 
213
        self.failUnlessEqual(result.testsRun, 1)
 
214
        self.failUnlessEqual(len(result.failures), 1)
 
215
 
 
216
    def test_loadNonMethod(self):
 
217
        import sample
 
218
        self.failUnlessRaises(TypeError, self.loader.loadMethod, sample)
 
219
        self.failUnlessRaises(TypeError,
 
220
                              self.loader.loadMethod, sample.FooTest)
 
221
        self.failUnlessRaises(TypeError, self.loader.loadMethod, "string")
 
222
        self.failUnlessRaises(TypeError,
 
223
                              self.loader.loadMethod, ('foo', 'bar'))
 
224
 
 
225
    def test_loadClass(self):
 
226
        import sample
 
227
        suite = self.loader.loadClass(sample.FooTest)
 
228
        self.failUnlessEqual(2, suite.countTestCases())
 
229
        self.failUnlessEqual(['test_bar', 'test_foo'],
 
230
                             [test._testMethodName for test in suite._tests])
 
231
 
 
232
 
 
233
    def test_loadNonClass(self):
 
234
        import sample
 
235
        self.failUnlessRaises(TypeError, self.loader.loadClass, sample)
 
236
        self.failUnlessRaises(TypeError,
 
237
                              self.loader.loadClass, sample.FooTest.test_foo)
 
238
        self.failUnlessRaises(TypeError, self.loader.loadClass, "string")
 
239
        self.failUnlessRaises(TypeError,
 
240
                              self.loader.loadClass, ('foo', 'bar'))
 
241
 
 
242
    def test_loadNonTestCase(self):
 
243
        import sample
 
244
        self.failUnlessRaises(ValueError, self.loader.loadClass,
 
245
                              sample.NotATest)
 
246
 
 
247
    def test_loadModule(self):
 
248
        import sample
 
249
        suite = self.loader.loadModule(sample)
 
250
        self.failUnlessEqual(7, suite.countTestCases())
 
251
 
 
252
    def test_loadNonModule(self):
 
253
        import sample
 
254
        self.failUnlessRaises(TypeError,
 
255
                              self.loader.loadModule, sample.FooTest)
 
256
        self.failUnlessRaises(TypeError,
 
257
                              self.loader.loadModule, sample.FooTest.test_foo)
 
258
        self.failUnlessRaises(TypeError, self.loader.loadModule, "string")
 
259
        self.failUnlessRaises(TypeError,
 
260
                              self.loader.loadModule, ('foo', 'bar'))
 
261
 
 
262
    def test_loadPackage(self):
 
263
        import goodpackage
 
264
        suite = self.loader.loadPackage(goodpackage)
 
265
        self.failUnlessEqual(7, suite.countTestCases())
 
266
 
 
267
    def test_loadNonPackage(self):
 
268
        import sample
 
269
        self.failUnlessRaises(TypeError,
 
270
                              self.loader.loadPackage, sample.FooTest)
 
271
        self.failUnlessRaises(TypeError,
 
272
                              self.loader.loadPackage, sample.FooTest.test_foo)
 
273
        self.failUnlessRaises(TypeError, self.loader.loadPackage, "string")
 
274
        self.failUnlessRaises(TypeError,
 
275
                              self.loader.loadPackage, ('foo', 'bar'))
 
276
 
 
277
    def test_loadModuleAsPackage(self):
 
278
        import sample
 
279
        ## XXX -- should this instead raise a ValueError? -- jml
 
280
        self.failUnlessRaises(TypeError, self.loader.loadPackage, sample)
 
281
 
 
282
    def test_loadPackageRecursive(self):
 
283
        import goodpackage
 
284
        suite = self.loader.loadPackage(goodpackage, recurse=True)
 
285
        self.failUnlessEqual(14, suite.countTestCases())
 
286
 
 
287
    def test_loadAnythingOnModule(self):
 
288
        import sample
 
289
        suite = self.loader.loadAnything(sample)
 
290
        self.failUnlessEqual(sample.__name__,
 
291
                             suite._tests[0]._tests[0].__class__.__module__)
 
292
 
 
293
    def test_loadAnythingOnClass(self):
 
294
        import sample
 
295
        suite = self.loader.loadAnything(sample.FooTest)
 
296
        self.failUnlessEqual(2, suite.countTestCases())
 
297
 
 
298
    def test_loadAnythingOnMethod(self):
 
299
        import sample
 
300
        suite = self.loader.loadAnything(sample.FooTest.test_foo)
 
301
        self.failUnlessEqual(1, suite.countTestCases())
 
302
 
 
303
    def test_loadAnythingOnPackage(self):
 
304
        import goodpackage
 
305
        suite = self.loader.loadAnything(goodpackage)
 
306
        self.failUnless(isinstance(suite, self.loader.suiteFactory))
 
307
        self.failUnlessEqual(7, suite.countTestCases())
 
308
 
 
309
    def test_loadAnythingOnPackageRecursive(self):
 
310
        import goodpackage
 
311
        suite = self.loader.loadAnything(goodpackage, recurse=True)
 
312
        self.failUnless(isinstance(suite, self.loader.suiteFactory))
 
313
        self.failUnlessEqual(14, suite.countTestCases())
 
314
 
 
315
    def test_loadAnythingOnString(self):
 
316
        # the important thing about this test is not the string-iness
 
317
        # but the non-handledness.
 
318
        self.failUnlessRaises(TypeError,
 
319
                              self.loader.loadAnything, "goodpackage")
 
320
 
 
321
    def test_importErrors(self):
 
322
        import package
 
323
        suite = self.loader.loadPackage(package, recurse=True)
 
324
        result = reporter.Reporter()
 
325
        suite.run(result)
 
326
        self.failUnlessEqual(False, result.wasSuccessful())
 
327
        self.failUnlessEqual(2, len(result.errors))
 
328
        errors = [test.id() for test, error in result.errors]
 
329
        errors.sort()
 
330
        self.failUnlessEqual(errors, ['package.test_bad_module',
 
331
                                      'package.test_import_module'])
 
332
 
 
333
 
 
334
    def test_differentInstances(self):
 
335
        """
 
336
        L{TestLoader.loadClass} returns a suite with each test method
 
337
        represented by a different instances of the L{TestCase} they are
 
338
        defined on.
 
339
        """
 
340
        class DistinctInstances(unittest.TestCase):
 
341
            def test_1(self):
 
342
                self.first = 'test1Run'
 
343
 
 
344
            def test_2(self):
 
345
                self.assertFalse(hasattr(self, 'first'))
 
346
 
 
347
        suite = self.loader.loadClass(DistinctInstances)
 
348
        result = reporter.Reporter()
 
349
        suite.run(result)
 
350
        self.assertTrue(result.wasSuccessful())
 
351
 
 
352
 
 
353
    def test_loadModuleWith_test_suite(self):
 
354
        """
 
355
        Check that C{test_suite} is used when present and other L{TestCase}s are
 
356
        not included.
 
357
        """
 
358
        from twisted.trial.test import mockcustomsuite
 
359
        suite = self.loader.loadModule(mockcustomsuite)
 
360
        self.failUnlessEqual(0, suite.countTestCases())
 
361
        self.failUnlessEqual("MyCustomSuite", getattr(suite, 'name', None))
 
362
 
 
363
 
 
364
    def test_loadModuleWith_testSuite(self):
 
365
        """
 
366
        Check that C{testSuite} is used when present and other L{TestCase}s are
 
367
        not included.
 
368
        """
 
369
        from twisted.trial.test import mockcustomsuite2
 
370
        suite = self.loader.loadModule(mockcustomsuite2)
 
371
        self.assertEqual(0, suite.countTestCases())
 
372
        self.assertEqual("MyCustomSuite", getattr(suite, 'name', None))
 
373
 
 
374
 
 
375
    def test_loadModuleWithBothCustom(self):
 
376
        """
 
377
        Check that if C{testSuite} and C{test_suite} are both present in a
 
378
        module then C{testSuite} gets priority.
 
379
        """
 
380
        from twisted.trial.test import mockcustomsuite3
 
381
        suite = self.loader.loadModule(mockcustomsuite3)
 
382
        self.assertEqual('testSuite', getattr(suite, 'name', None))
 
383
 
 
384
 
 
385
    def test_customLoadRaisesAttributeError(self):
 
386
        """
 
387
        Make sure that any C{AttributeError}s raised by C{testSuite} are not
 
388
        swallowed by L{TestLoader}.
 
389
        """
 
390
        def testSuite():
 
391
            raise AttributeError('should be reraised')
 
392
        from twisted.trial.test import mockcustomsuite2
 
393
        mockcustomsuite2.testSuite, original = (testSuite,
 
394
                                                mockcustomsuite2.testSuite)
 
395
        try:
 
396
            self.assertRaises(AttributeError, self.loader.loadModule,
 
397
                              mockcustomsuite2)
 
398
        finally:
 
399
            mockcustomsuite2.testSuite = original
 
400
 
 
401
 
 
402
    # XXX - duplicated and modified from test_script
 
403
    def assertSuitesEqual(self, test1, test2):
 
404
        names1 = testNames(test1)
 
405
        names2 = testNames(test2)
 
406
        names1.sort()
 
407
        names2.sort()
 
408
        self.assertEqual(names1, names2)
 
409
 
 
410
    def test_loadByNamesDuplicate(self):
 
411
        """
 
412
        Check that loadByNames ignores duplicate names
 
413
        """
 
414
        module = 'twisted.trial.test.test_test_visitor'
 
415
        suite1 = self.loader.loadByNames([module, module], True)
 
416
        suite2 = self.loader.loadByName(module, True)
 
417
        self.assertSuitesEqual(suite1, suite2)
 
418
 
 
419
    def test_loadDifferentNames(self):
 
420
        """
 
421
        Check that loadByNames loads all the names that it is given
 
422
        """
 
423
        modules = ['goodpackage', 'package.test_module']
 
424
        suite1 = self.loader.loadByNames(modules)
 
425
        suite2 = runner.TestSuite(map(self.loader.loadByName, modules))
 
426
        self.assertSuitesEqual(suite1, suite2)
 
427
 
 
428
 
 
429
 
 
430
class ZipLoadingTest(LoaderTest):
 
431
    def setUp(self):
 
432
        from twisted.test.test_paths import zipit
 
433
        LoaderTest.setUp(self)
 
434
        zipit(self.parent, self.parent+'.zip')
 
435
        self.parent += '.zip'
 
436
        self.mangleSysPath(self.oldPath+[self.parent])
 
437
 
 
438
 
 
439
 
 
440
class PackageOrderingTest(packages.SysPathManglingTest):
 
441
    if sys.version_info < (2, 4):
 
442
        skip = (
 
443
            "Python 2.3 import semantics make this behavior incorrect on that "
 
444
            "version of Python as well as difficult to test.  The second "
 
445
            "import of a package which raised an exception the first time it "
 
446
            "was imported will succeed on Python 2.3, whereas it will fail on "
 
447
            "later versions of Python.  Trial does not account for this, so "
 
448
            "this test fails with inconsistencies between the expected and "
 
449
            "the received loader errors.")
 
450
 
 
451
    def setUp(self):
 
452
        self.loader = runner.TestLoader()
 
453
        self.topDir = self.mktemp()
 
454
        parent = os.path.join(self.topDir, "uberpackage")
 
455
        os.makedirs(parent)
 
456
        file(os.path.join(parent, "__init__.py"), "wb").close()
 
457
        packages.SysPathManglingTest.setUp(self, parent)
 
458
        self.mangleSysPath(self.oldPath + [self.topDir])
 
459
 
 
460
    def _trialSortAlgorithm(self, sorter):
 
461
        """
 
462
        Right now, halfway by accident, trial sorts like this:
 
463
 
 
464
            1. all modules are grouped together in one list and sorted.
 
465
 
 
466
            2. within each module, the classes are grouped together in one list
 
467
               and sorted.
 
468
 
 
469
            3. finally within each class, each test method is grouped together
 
470
               in a list and sorted.
 
471
 
 
472
        This attempts to return a sorted list of testable thingies following
 
473
        those rules, so that we can compare the behavior of loadPackage.
 
474
 
 
475
        The things that show as 'cases' are errors from modules which failed to
 
476
        import, and test methods.  Let's gather all those together.
 
477
        """
 
478
        pkg = getModule('uberpackage')
 
479
        testModules = []
 
480
        for testModule in pkg.walkModules():
 
481
            if testModule.name.split(".")[-1].startswith("test_"):
 
482
                testModules.append(testModule)
 
483
        sortedModules = util.dsu(testModules, sorter) # ONE
 
484
        for modinfo in sortedModules:
 
485
            # Now let's find all the classes.
 
486
            module = modinfo.load(None)
 
487
            if module is None:
 
488
                yield modinfo
 
489
            else:
 
490
                testClasses = []
 
491
                for attrib in modinfo.iterAttributes():
 
492
                    if runner.isTestCase(attrib.load()):
 
493
                        testClasses.append(attrib)
 
494
                sortedClasses = util.dsu(testClasses, sorter) # TWO
 
495
                for clsinfo in sortedClasses:
 
496
                    testMethods = []
 
497
                    for attr in clsinfo.iterAttributes():
 
498
                        if attr.name.split(".")[-1].startswith('test'):
 
499
                            testMethods.append(attr)
 
500
                    sortedMethods = util.dsu(testMethods, sorter) # THREE
 
501
                    for methinfo in sortedMethods:
 
502
                        yield methinfo
 
503
 
 
504
 
 
505
    def loadSortedPackages(self, sorter=runner.name):
 
506
        """
 
507
        Verify that packages are loaded in the correct order.
 
508
        """
 
509
        import uberpackage
 
510
        self.loader.sorter = sorter
 
511
        suite = self.loader.loadPackage(uberpackage, recurse=True)
 
512
        # XXX: Work around strange, unexplained Zope crap.
 
513
        # jml, 2007-11-15.
 
514
        suite = unittest.decorate(suite, ITestCase)
 
515
        resultingTests = list(unittest._iterateTests(suite))
 
516
        manifest = list(self._trialSortAlgorithm(sorter))
 
517
        for number, (manifestTest, actualTest) in enumerate(
 
518
            zip(manifest, resultingTests)):
 
519
            self.assertEqual(
 
520
                 manifestTest.name, actualTest.id(),
 
521
                 "#%d: %s != %s" %
 
522
                 (number, manifestTest.name, actualTest.id()))
 
523
        self.assertEqual(len(manifest), len(resultingTests))
 
524
 
 
525
 
 
526
    def test_sortPackagesDefaultOrder(self):
 
527
        self.loadSortedPackages()
 
528
 
 
529
 
 
530
    def test_sortPackagesSillyOrder(self):
 
531
        def sillySorter(s):
 
532
            # This has to work on fully-qualified class names and class
 
533
            # objects, which is silly, but it's the "spec", such as it is.
 
534
#             if isinstance(s, type) or isinstance(s, types.ClassType):
 
535
#                 return s.__module__+'.'+s.__name__
 
536
            n = runner.name(s)
 
537
            d = md5(n).hexdigest()
 
538
            return d
 
539
        self.loadSortedPackages(sillySorter)
 
540
 
 
541