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