Imported Upstream version 1.2.1
[platform/upstream/python-nose.git] / nose / core.py
1 """Implements nose test program and collector.
2 """
3 from __future__ import generators
4
5 import logging
6 import os
7 import sys
8 import time
9 import unittest
10
11 from nose.config import Config, all_config_files
12 from nose.loader import defaultTestLoader
13 from nose.plugins.manager import PluginManager, DefaultPluginManager, \
14      RestrictedPluginManager
15 from nose.result import TextTestResult
16 from nose.suite import FinalizingSuiteWrapper
17 from nose.util import isclass, tolist
18
19
20 log = logging.getLogger('nose.core')
21 compat_24 = sys.version_info >= (2, 4)
22
23 __all__ = ['TestProgram', 'main', 'run', 'run_exit', 'runmodule', 'collector',
24            'TextTestRunner']
25
26
27 class TextTestRunner(unittest.TextTestRunner):
28     """Test runner that uses nose's TextTestResult to enable errorClasses,
29     as well as providing hooks for plugins to override or replace the test
30     output stream, results, and the test case itself.
31     """
32     def __init__(self, stream=sys.stderr, descriptions=1, verbosity=1,
33                  config=None):
34         if config is None:
35             config = Config()
36         self.config = config
37         unittest.TextTestRunner.__init__(self, stream, descriptions, verbosity)
38
39
40     def _makeResult(self):
41         return TextTestResult(self.stream,
42                               self.descriptions,
43                               self.verbosity,
44                               self.config)
45
46     def run(self, test):
47         """Overrides to provide plugin hooks and defer all output to
48         the test result class.
49         """
50         wrapper = self.config.plugins.prepareTest(test)
51         if wrapper is not None:
52             test = wrapper
53
54         # plugins can decorate or capture the output stream
55         wrapped = self.config.plugins.setOutputStream(self.stream)
56         if wrapped is not None:
57             self.stream = wrapped
58
59         result = self._makeResult()
60         start = time.time()
61         test(result)
62         stop = time.time()
63         result.printErrors()
64         result.printSummary(start, stop)
65         self.config.plugins.finalize(result)
66         return result
67
68
69 class TestProgram(unittest.TestProgram):
70     """Collect and run tests, returning success or failure.
71
72     The arguments to TestProgram() are the same as to
73     :func:`main()` and :func:`run()`:
74
75     * module: All tests are in this module (default: None)
76     * defaultTest: Tests to load (default: '.')
77     * argv: Command line arguments (default: None; sys.argv is read)
78     * testRunner: Test runner instance (default: None)
79     * testLoader: Test loader instance (default: None)
80     * env: Environment; ignored if config is provided (default: None;
81       os.environ is read)
82     * config: :class:`nose.config.Config` instance (default: None)
83     * suite: Suite or list of tests to run (default: None). Passing a
84       suite or lists of tests will bypass all test discovery and
85       loading. *ALSO NOTE* that if you pass a unittest.TestSuite
86       instance as the suite, context fixtures at the class, module and
87       package level will not be used, and many plugin hooks will not
88       be called. If you want normal nose behavior, either pass a list
89       of tests, or a fully-configured :class:`nose.suite.ContextSuite`.
90     * exit: Exit after running tests and printing report (default: True)
91     * plugins: List of plugins to use; ignored if config is provided
92       (default: load plugins with DefaultPluginManager)
93     * addplugins: List of **extra** plugins to use. Pass a list of plugin
94       instances in this argument to make custom plugins available while
95       still using the DefaultPluginManager.
96     """
97     verbosity = 1
98
99     def __init__(self, module=None, defaultTest='.', argv=None,
100                  testRunner=None, testLoader=None, env=None, config=None,
101                  suite=None, exit=True, plugins=None, addplugins=None):
102         if env is None:
103             env = os.environ
104         if config is None:
105             config = self.makeConfig(env, plugins)
106         if addplugins:
107             config.plugins.addPlugins(extraplugins=addplugins)
108         self.config = config
109         self.suite = suite
110         self.exit = exit
111         extra_args = {}
112         version = sys.version_info[0:2]
113         if version >= (2,7) and version != (3,0):
114             extra_args['exit'] = exit
115         unittest.TestProgram.__init__(
116             self, module=module, defaultTest=defaultTest,
117             argv=argv, testRunner=testRunner, testLoader=testLoader,
118             **extra_args)
119
120     def makeConfig(self, env, plugins=None):
121         """Load a Config, pre-filled with user config files if any are
122         found.
123         """
124         cfg_files = all_config_files()
125         if plugins:
126             manager = PluginManager(plugins=plugins)
127         else:
128             manager = DefaultPluginManager()
129         return Config(
130             env=env, files=cfg_files, plugins=manager)
131
132     def parseArgs(self, argv):
133         """Parse argv and env and configure running environment.
134         """
135         self.config.configure(argv, doc=self.usage())
136         log.debug("configured %s", self.config)
137
138         # quick outs: version, plugins (optparse would have already
139         # caught and exited on help)
140         if self.config.options.version:
141             from nose import __version__
142             sys.stdout = sys.__stdout__
143             print "%s version %s" % (os.path.basename(sys.argv[0]), __version__)
144             sys.exit(0)
145
146         if self.config.options.showPlugins:
147             self.showPlugins()
148             sys.exit(0)
149
150         if self.testLoader is None:
151             self.testLoader = defaultTestLoader(config=self.config)
152         elif isclass(self.testLoader):
153             self.testLoader = self.testLoader(config=self.config)
154         plug_loader = self.config.plugins.prepareTestLoader(self.testLoader)
155         if plug_loader is not None:
156             self.testLoader = plug_loader
157         log.debug("test loader is %s", self.testLoader)
158
159         # FIXME if self.module is a string, add it to self.testNames? not sure
160
161         if self.config.testNames:
162             self.testNames = self.config.testNames
163         else:
164             self.testNames = tolist(self.defaultTest)
165         log.debug('defaultTest %s', self.defaultTest)
166         log.debug('Test names are %s', self.testNames)
167         if self.config.workingDir is not None:
168             os.chdir(self.config.workingDir)
169         self.createTests()
170
171     def createTests(self):
172         """Create the tests to run. If a self.suite
173         is set, then that suite will be used. Otherwise, tests will be
174         loaded from the given test names (self.testNames) using the
175         test loader.
176         """
177         log.debug("createTests called with %s", self.suite)
178         if self.suite is not None:
179             # We were given an explicit suite to run. Make sure it's
180             # loaded and wrapped correctly.
181             self.test = self.testLoader.suiteClass(self.suite)
182         else:
183             self.test = self.testLoader.loadTestsFromNames(self.testNames)
184
185     def runTests(self):
186         """Run Tests. Returns true on success, false on failure, and sets
187         self.success to the same value.
188         """
189         log.debug("runTests called")
190         if self.testRunner is None:
191             self.testRunner = TextTestRunner(stream=self.config.stream,
192                                              verbosity=self.config.verbosity,
193                                              config=self.config)
194         plug_runner = self.config.plugins.prepareTestRunner(self.testRunner)
195         if plug_runner is not None:
196             self.testRunner = plug_runner
197         result = self.testRunner.run(self.test)
198         self.success = result.wasSuccessful()
199         if self.exit:
200             sys.exit(not self.success)
201         return self.success
202
203     def showPlugins(self):
204         """Print list of available plugins.
205         """
206         import textwrap
207
208         class DummyParser:
209             def __init__(self):
210                 self.options = []
211             def add_option(self, *arg, **kw):
212                 self.options.append((arg, kw.pop('help', '')))
213
214         v = self.config.verbosity
215         self.config.plugins.sort()
216         for p in self.config.plugins:
217             print "Plugin %s" % p.name
218             if v >= 2:
219                 print "  score: %s" % p.score
220                 print '\n'.join(textwrap.wrap(p.help().strip(),
221                                               initial_indent='  ',
222                                               subsequent_indent='  '))
223                 if v >= 3:
224                     parser = DummyParser()
225                     p.addOptions(parser)
226                     if len(parser.options):
227                         print
228                         print "  Options:"
229                         for opts, help in parser.options:
230                             print '  %s' % (', '.join(opts))
231                             if help:
232                                 print '\n'.join(
233                                     textwrap.wrap(help.strip(),
234                                                   initial_indent='    ',
235                                                   subsequent_indent='    '))
236                 print
237
238     def usage(cls):
239         import nose
240         if hasattr(nose, '__loader__'):
241             ld = nose.__loader__
242             if hasattr(ld, 'zipfile'):
243                 # nose was imported from a zipfile
244                 return ld.get_data(
245                         os.path.join(ld.prefix, 'nose', 'usage.txt'))
246         return open(os.path.join(
247                 os.path.dirname(__file__), 'usage.txt'), 'r').read()
248     usage = classmethod(usage)
249
250 # backwards compatibility
251 run_exit = main = TestProgram
252
253
254 def run(*arg, **kw):
255     """Collect and run tests, returning success or failure.
256
257     The arguments to `run()` are the same as to `main()`:
258
259     * module: All tests are in this module (default: None)
260     * defaultTest: Tests to load (default: '.')
261     * argv: Command line arguments (default: None; sys.argv is read)
262     * testRunner: Test runner instance (default: None)
263     * testLoader: Test loader instance (default: None)
264     * env: Environment; ignored if config is provided (default: None;
265       os.environ is read)
266     * config: :class:`nose.config.Config` instance (default: None)
267     * suite: Suite or list of tests to run (default: None). Passing a
268       suite or lists of tests will bypass all test discovery and
269       loading. *ALSO NOTE* that if you pass a unittest.TestSuite
270       instance as the suite, context fixtures at the class, module and
271       package level will not be used, and many plugin hooks will not
272       be called. If you want normal nose behavior, either pass a list
273       of tests, or a fully-configured :class:`nose.suite.ContextSuite`.
274     * plugins: List of plugins to use; ignored if config is provided
275       (default: load plugins with DefaultPluginManager)
276     * addplugins: List of **extra** plugins to use. Pass a list of plugin
277       instances in this argument to make custom plugins available while
278       still using the DefaultPluginManager.
279
280     With the exception that the ``exit`` argument is always set
281     to False.
282     """
283     kw['exit'] = False
284     return TestProgram(*arg, **kw).success
285
286
287 def runmodule(name='__main__', **kw):
288     """Collect and run tests in a single module only. Defaults to running
289     tests in __main__. Additional arguments to TestProgram may be passed
290     as keyword arguments.
291     """
292     main(defaultTest=name, **kw)
293
294
295 def collector():
296     """TestSuite replacement entry point. Use anywhere you might use a
297     unittest.TestSuite. The collector will, by default, load options from
298     all config files and execute loader.loadTestsFromNames() on the
299     configured testNames, or '.' if no testNames are configured.
300     """
301     # plugins that implement any of these methods are disabled, since
302     # we don't control the test runner and won't be able to run them
303     # finalize() is also not called, but plugins that use it aren't disabled,
304     # because capture needs it.
305     setuptools_incompat = ('report', 'prepareTest',
306                            'prepareTestLoader', 'prepareTestRunner',
307                            'setOutputStream')
308
309     plugins = RestrictedPluginManager(exclude=setuptools_incompat)
310     conf = Config(files=all_config_files(),
311                   plugins=plugins)
312     conf.configure(argv=['collector'])
313     loader = defaultTestLoader(conf)
314
315     if conf.testNames:
316         suite = loader.loadTestsFromNames(conf.testNames)
317     else:
318         suite = loader.loadTestsFromNames(('.',))
319     return FinalizingSuiteWrapper(suite, plugins.finalize)
320
321
322
323 if __name__ == '__main__':
324     main()