Phillip J. Eby | 069159b | 2006-04-18 04:05:34 +0000 | [diff] [blame] | 1 | from setuptools import Command |
| 2 | from distutils.errors import DistutilsOptionError |
| 3 | import sys |
| 4 | from pkg_resources import * |
| 5 | from unittest import TestLoader, main |
| 6 | |
| 7 | class ScanningLoader(TestLoader): |
| 8 | |
| 9 | def loadTestsFromModule(self, module): |
| 10 | """Return a suite of all tests cases contained in the given module |
| 11 | |
| 12 | If the module is a package, load tests from all the modules in it. |
| 13 | If the module has an ``additional_tests`` function, call it and add |
| 14 | the return value to the tests. |
| 15 | """ |
| 16 | tests = [] |
| 17 | if module.__name__!='setuptools.tests.doctest': # ugh |
| 18 | tests.append(TestLoader.loadTestsFromModule(self,module)) |
| 19 | |
| 20 | if hasattr(module, "additional_tests"): |
| 21 | tests.append(module.additional_tests()) |
| 22 | |
| 23 | if hasattr(module, '__path__'): |
| 24 | for file in resource_listdir(module.__name__, ''): |
| 25 | if file.endswith('.py') and file!='__init__.py': |
| 26 | submodule = module.__name__+'.'+file[:-3] |
| 27 | else: |
| 28 | if resource_exists( |
| 29 | module.__name__, file+'/__init__.py' |
| 30 | ): |
| 31 | submodule = module.__name__+'.'+file |
| 32 | else: |
| 33 | continue |
| 34 | tests.append(self.loadTestsFromName(submodule)) |
| 35 | |
| 36 | if len(tests)!=1: |
| 37 | return self.suiteClass(tests) |
| 38 | else: |
| 39 | return tests[0] # don't create a nested suite for only one return |
| 40 | |
| 41 | |
| 42 | class test(Command): |
| 43 | |
| 44 | """Command to run unit tests after in-place build""" |
| 45 | |
| 46 | description = "run unit tests after in-place build" |
| 47 | |
| 48 | user_options = [ |
| 49 | ('test-module=','m', "Run 'test_suite' in specified module"), |
| 50 | ('test-suite=','s', |
| 51 | "Test suite to run (e.g. 'some_module.test_suite')"), |
| 52 | ] |
| 53 | |
| 54 | def initialize_options(self): |
| 55 | self.test_suite = None |
| 56 | self.test_module = None |
| 57 | self.test_loader = None |
| 58 | |
| 59 | |
| 60 | def finalize_options(self): |
| 61 | |
| 62 | if self.test_suite is None: |
| 63 | if self.test_module is None: |
| 64 | self.test_suite = self.distribution.test_suite |
| 65 | else: |
| 66 | self.test_suite = self.test_module+".test_suite" |
| 67 | elif self.test_module: |
| 68 | raise DistutilsOptionError( |
| 69 | "You may specify a module or a suite, but not both" |
| 70 | ) |
| 71 | |
| 72 | self.test_args = [self.test_suite] |
| 73 | |
| 74 | if self.verbose: |
| 75 | self.test_args.insert(0,'--verbose') |
| 76 | if self.test_loader is None: |
| 77 | self.test_loader = getattr(self.distribution,'test_loader',None) |
| 78 | if self.test_loader is None: |
| 79 | self.test_loader = "setuptools.command.test:ScanningLoader" |
| 80 | |
| 81 | |
| 82 | |
| 83 | def run(self): |
| 84 | # Ensure metadata is up-to-date |
| 85 | self.run_command('egg_info') |
| 86 | |
| 87 | # Build extensions in-place |
| 88 | self.reinitialize_command('build_ext', inplace=1) |
| 89 | self.run_command('build_ext') |
| 90 | |
| 91 | if self.distribution.tests_require: |
| 92 | self.distribution.fetch_build_eggs(self.distribution.tests_require) |
| 93 | |
| 94 | if self.test_suite: |
| 95 | cmd = ' '.join(self.test_args) |
| 96 | if self.dry_run: |
| 97 | self.announce('skipping "unittest %s" (dry run)' % cmd) |
| 98 | else: |
| 99 | self.announce('running "unittest %s"' % cmd) |
| 100 | self.run_tests() |
| 101 | |
| 102 | |
| 103 | def run_tests(self): |
| 104 | import unittest |
| 105 | old_path = sys.path[:] |
| 106 | ei_cmd = self.get_finalized_command("egg_info") |
| 107 | path_item = normalize_path(ei_cmd.egg_base) |
| 108 | metadata = PathMetadata( |
| 109 | path_item, normalize_path(ei_cmd.egg_info) |
| 110 | ) |
| 111 | dist = Distribution(path_item, metadata, project_name=ei_cmd.egg_name) |
| 112 | working_set.add(dist) |
| 113 | require(str(dist.as_requirement())) |
| 114 | loader_ep = EntryPoint.parse("x="+self.test_loader) |
| 115 | loader_class = loader_ep.load(require=False) |
| 116 | unittest.main( |
| 117 | None, None, [unittest.__file__]+self.test_args, |
| 118 | testLoader = loader_class() |
| 119 | ) |
| 120 | |
| 121 | |
| 122 | |
| 123 | |