1 from setuptools import Command
2 from distutils.errors import DistutilsOptionError
4 from pkg_resources import *
5 from unittest import TestLoader, main
7 class ScanningLoader(TestLoader):
9 def loadTestsFromModule(self, module):
10 """Return a suite of all tests cases contained in the given module
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.
17 if module.__name__!='setuptools.tests.doctest': # ugh
18 tests.append(TestLoader.loadTestsFromModule(self,module))
20 if hasattr(module, "additional_tests"):
21 tests.append(module.additional_tests())
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]
29 module.__name__, file+'/__init__.py'
31 submodule = module.__name__+'.'+file
34 tests.append(self.loadTestsFromName(submodule))
37 return self.suiteClass(tests)
39 return tests[0] # don't create a nested suite for only one return
43 """Command to run unit tests after in-place build"""
45 description = "run unit tests after in-place build"
48 ('test-module=','m', "Run 'test_suite' in specified module"),
50 "Test suite to run (e.g. 'some_module.test_suite')"),
51 ('test-runner=','r', "Test runner to use"),
54 def initialize_options(self):
55 self.test_runner = None
56 self.test_suite = None
57 self.test_module = None
58 self.test_loader = None
60 def finalize_options(self):
61 if self.test_suite is None:
62 if self.test_module is None:
63 self.test_suite = self.distribution.test_suite
65 self.test_suite = self.test_module+".test_suite"
66 elif self.test_module:
67 raise DistutilsOptionError(
68 "You may specify a module or a suite, but not both"
71 self.test_args = [self.test_suite]
74 self.test_args.insert(0,'--verbose')
75 if self.test_loader is None:
76 self.test_loader = getattr(self.distribution,'test_loader',None)
77 if self.test_loader is None:
78 self.test_loader = "setuptools.command.test:ScanningLoader"
79 if self.test_runner is None:
80 self.test_runner = getattr(self.distribution,'test_runner',None)
83 def with_project_on_sys_path(self, func):
84 # Ensure metadata is up-to-date
85 self.run_command('egg_info')
87 # Build extensions in-place
88 self.reinitialize_command('build_ext', inplace=1)
89 self.run_command('build_ext')
91 ei_cmd = self.get_finalized_command("egg_info")
93 old_path = sys.path[:]
94 old_modules = sys.modules.copy()
97 sys.path.insert(0, normalize_path(ei_cmd.egg_base))
98 working_set.__init__()
99 add_activation_listener(lambda dist: dist.activate())
100 require('%s==%s' % (ei_cmd.egg_name, ei_cmd.egg_version))
103 sys.path[:] = old_path
105 sys.modules.update(old_modules)
106 working_set.__init__()
110 if self.distribution.install_requires:
111 self.distribution.fetch_build_eggs(self.distribution.install_requires)
112 if self.distribution.tests_require:
113 self.distribution.fetch_build_eggs(self.distribution.tests_require)
116 cmd = ' '.join(self.test_args)
118 self.announce('skipping "unittest %s" (dry run)' % cmd)
120 self.announce('running "unittest %s"' % cmd)
121 self.with_project_on_sys_path(self.run_tests)
126 loader_ep = EntryPoint.parse("x="+self.test_loader)
127 loader_class = loader_ep.load(require=False)
129 if self.test_runner is not None:
130 runner_ep = EntryPoint.parse("x="+self.test_runner)
131 runner_class = runner_ep.load(require=False)
132 kw['testRunner'] = runner_class()
134 None, None, [unittest.__file__]+self.test_args,
135 testLoader = loader_class(), **kw