blob: 83589fa922ff4459e0c51a5c2dbaf9cb8d324096 [file] [log] [blame]
Phillip J. Eby069159b2006-04-18 04:05:34 +00001from setuptools import Command
2from distutils.errors import DistutilsOptionError
3import sys
4from pkg_resources import *
5from unittest import TestLoader, main
6
7class 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
42class 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