base.py 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725
  1. import os
  2. import textwrap
  3. from optparse import OptionConflictError
  4. from warnings import warn
  5. from nose.util import tolist
  6. class Plugin(object):
  7. """Base class for nose plugins. It's recommended but not *necessary* to
  8. subclass this class to create a plugin, but all plugins *must* implement
  9. `options(self, parser, env)` and `configure(self, options, conf)`, and
  10. must have the attributes `enabled`, `name` and `score`. The `name`
  11. attribute may contain hyphens ('-').
  12. Plugins should not be enabled by default.
  13. Subclassing Plugin (and calling the superclass methods in
  14. __init__, configure, and options, if you override them) will give
  15. your plugin some friendly default behavior:
  16. * A --with-$name option will be added to the command line interface
  17. to enable the plugin, and a corresponding environment variable
  18. will be used as the default value. The plugin class's docstring
  19. will be used as the help for this option.
  20. * The plugin will not be enabled unless this option is selected by
  21. the user.
  22. """
  23. can_configure = False
  24. enabled = False
  25. enableOpt = None
  26. name = None
  27. score = 100
  28. def __init__(self):
  29. if self.name is None:
  30. self.name = self.__class__.__name__.lower()
  31. if self.enableOpt is None:
  32. self.enableOpt = "enable_plugin_%s" % self.name.replace('-', '_')
  33. def addOptions(self, parser, env=None):
  34. """Add command-line options for this plugin.
  35. The base plugin class adds --with-$name by default, used to enable the
  36. plugin.
  37. .. warning :: Don't implement addOptions unless you want to override
  38. all default option handling behavior, including
  39. warnings for conflicting options. Implement
  40. :meth:`options
  41. <nose.plugins.base.IPluginInterface.options>`
  42. instead.
  43. """
  44. self.add_options(parser, env)
  45. def add_options(self, parser, env=None):
  46. """Non-camel-case version of func name for backwards compatibility.
  47. .. warning ::
  48. DEPRECATED: Do not use this method,
  49. use :meth:`options <nose.plugins.base.IPluginInterface.options>`
  50. instead.
  51. """
  52. # FIXME raise deprecation warning if wasn't called by wrapper
  53. if env is None:
  54. env = os.environ
  55. try:
  56. self.options(parser, env)
  57. self.can_configure = True
  58. except OptionConflictError, e:
  59. warn("Plugin %s has conflicting option string: %s and will "
  60. "be disabled" % (self, e), RuntimeWarning)
  61. self.enabled = False
  62. self.can_configure = False
  63. def options(self, parser, env):
  64. """Register commandline options.
  65. Implement this method for normal options behavior with protection from
  66. OptionConflictErrors. If you override this method and want the default
  67. --with-$name option to be registered, be sure to call super().
  68. """
  69. env_opt = 'NOSE_WITH_%s' % self.name.upper()
  70. env_opt = env_opt.replace('-', '_')
  71. parser.add_option("--with-%s" % self.name,
  72. action="store_true",
  73. dest=self.enableOpt,
  74. default=env.get(env_opt),
  75. help="Enable plugin %s: %s [%s]" %
  76. (self.__class__.__name__, self.help(), env_opt))
  77. def configure(self, options, conf):
  78. """Configure the plugin and system, based on selected options.
  79. The base plugin class sets the plugin to enabled if the enable option
  80. for the plugin (self.enableOpt) is true.
  81. """
  82. if not self.can_configure:
  83. return
  84. self.conf = conf
  85. if hasattr(options, self.enableOpt):
  86. self.enabled = getattr(options, self.enableOpt)
  87. def help(self):
  88. """Return help for this plugin. This will be output as the help
  89. section of the --with-$name option that enables the plugin.
  90. """
  91. if self.__class__.__doc__:
  92. # doc sections are often indented; compress the spaces
  93. return textwrap.dedent(self.__class__.__doc__)
  94. return "(no help available)"
  95. # Compatiblity shim
  96. def tolist(self, val):
  97. warn("Plugin.tolist is deprecated. Use nose.util.tolist instead",
  98. DeprecationWarning)
  99. return tolist(val)
  100. class IPluginInterface(object):
  101. """
  102. IPluginInterface describes the plugin API. Do not subclass or use this
  103. class directly.
  104. """
  105. def __new__(cls, *arg, **kw):
  106. raise TypeError("IPluginInterface class is for documentation only")
  107. def addOptions(self, parser, env):
  108. """Called to allow plugin to register command-line options with the
  109. parser. DO NOT return a value from this method unless you want to stop
  110. all other plugins from setting their options.
  111. .. warning ::
  112. DEPRECATED -- implement
  113. :meth:`options <nose.plugins.base.IPluginInterface.options>` instead.
  114. """
  115. pass
  116. add_options = addOptions
  117. add_options.deprecated = True
  118. def addDeprecated(self, test):
  119. """Called when a deprecated test is seen. DO NOT return a value
  120. unless you want to stop other plugins from seeing the deprecated
  121. test.
  122. .. warning :: DEPRECATED -- check error class in addError instead
  123. """
  124. pass
  125. addDeprecated.deprecated = True
  126. def addError(self, test, err):
  127. """Called when a test raises an uncaught exception. DO NOT return a
  128. value unless you want to stop other plugins from seeing that the
  129. test has raised an error.
  130. :param test: the test case
  131. :type test: :class:`nose.case.Test`
  132. :param err: sys.exc_info() tuple
  133. :type err: 3-tuple
  134. """
  135. pass
  136. addError.changed = True
  137. def addFailure(self, test, err):
  138. """Called when a test fails. DO NOT return a value unless you
  139. want to stop other plugins from seeing that the test has failed.
  140. :param test: the test case
  141. :type test: :class:`nose.case.Test`
  142. :param err: 3-tuple
  143. :type err: sys.exc_info() tuple
  144. """
  145. pass
  146. addFailure.changed = True
  147. def addSkip(self, test):
  148. """Called when a test is skipped. DO NOT return a value unless
  149. you want to stop other plugins from seeing the skipped test.
  150. .. warning:: DEPRECATED -- check error class in addError instead
  151. """
  152. pass
  153. addSkip.deprecated = True
  154. def addSuccess(self, test):
  155. """Called when a test passes. DO NOT return a value unless you
  156. want to stop other plugins from seeing the passing test.
  157. :param test: the test case
  158. :type test: :class:`nose.case.Test`
  159. """
  160. pass
  161. addSuccess.changed = True
  162. def afterContext(self):
  163. """Called after a context (generally a module) has been
  164. lazy-loaded, imported, setup, had its tests loaded and
  165. executed, and torn down.
  166. """
  167. pass
  168. afterContext._new = True
  169. def afterDirectory(self, path):
  170. """Called after all tests have been loaded from directory at path
  171. and run.
  172. :param path: the directory that has finished processing
  173. :type path: string
  174. """
  175. pass
  176. afterDirectory._new = True
  177. def afterImport(self, filename, module):
  178. """Called after module is imported from filename. afterImport
  179. is called even if the import failed.
  180. :param filename: The file that was loaded
  181. :type filename: string
  182. :param module: The name of the module
  183. :type module: string
  184. """
  185. pass
  186. afterImport._new = True
  187. def afterTest(self, test):
  188. """Called after the test has been run and the result recorded
  189. (after stopTest).
  190. :param test: the test case
  191. :type test: :class:`nose.case.Test`
  192. """
  193. pass
  194. afterTest._new = True
  195. def beforeContext(self):
  196. """Called before a context (generally a module) is
  197. examined. Because the context is not yet loaded, plugins don't
  198. get to know what the context is; so any context operations
  199. should use a stack that is pushed in `beforeContext` and popped
  200. in `afterContext` to ensure they operate symmetrically.
  201. `beforeContext` and `afterContext` are mainly useful for tracking
  202. and restoring global state around possible changes from within a
  203. context, whatever the context may be. If you need to operate on
  204. contexts themselves, see `startContext` and `stopContext`, which
  205. are passed the context in question, but are called after
  206. it has been loaded (imported in the module case).
  207. """
  208. pass
  209. beforeContext._new = True
  210. def beforeDirectory(self, path):
  211. """Called before tests are loaded from directory at path.
  212. :param path: the directory that is about to be processed
  213. """
  214. pass
  215. beforeDirectory._new = True
  216. def beforeImport(self, filename, module):
  217. """Called before module is imported from filename.
  218. :param filename: The file that will be loaded
  219. :param module: The name of the module found in file
  220. :type module: string
  221. """
  222. beforeImport._new = True
  223. def beforeTest(self, test):
  224. """Called before the test is run (before startTest).
  225. :param test: the test case
  226. :type test: :class:`nose.case.Test`
  227. """
  228. pass
  229. beforeTest._new = True
  230. def begin(self):
  231. """Called before any tests are collected or run. Use this to
  232. perform any setup needed before testing begins.
  233. """
  234. pass
  235. def configure(self, options, conf):
  236. """Called after the command line has been parsed, with the
  237. parsed options and the config container. Here, implement any
  238. config storage or changes to state or operation that are set
  239. by command line options.
  240. DO NOT return a value from this method unless you want to
  241. stop all other plugins from being configured.
  242. """
  243. pass
  244. def finalize(self, result):
  245. """Called after all report output, including output from all
  246. plugins, has been sent to the stream. Use this to print final
  247. test results or perform final cleanup. Return None to allow
  248. other plugins to continue printing, or any other value to stop
  249. them.
  250. :param result: test result object
  251. .. Note:: When tests are run under a test runner other than
  252. :class:`nose.core.TextTestRunner`, such as
  253. via ``python setup.py test``, this method may be called
  254. **before** the default report output is sent.
  255. """
  256. pass
  257. def describeTest(self, test):
  258. """Return a test description.
  259. Called by :meth:`nose.case.Test.shortDescription`.
  260. :param test: the test case
  261. :type test: :class:`nose.case.Test`
  262. """
  263. pass
  264. describeTest._new = True
  265. def formatError(self, test, err):
  266. """Called in result.addError, before plugin.addError. If you
  267. want to replace or modify the error tuple, return a new error
  268. tuple, otherwise return err, the original error tuple.
  269. :param test: the test case
  270. :type test: :class:`nose.case.Test`
  271. :param err: sys.exc_info() tuple
  272. :type err: 3-tuple
  273. """
  274. pass
  275. formatError._new = True
  276. formatError.chainable = True
  277. # test arg is not chainable
  278. formatError.static_args = (True, False)
  279. def formatFailure(self, test, err):
  280. """Called in result.addFailure, before plugin.addFailure. If you
  281. want to replace or modify the error tuple, return a new error
  282. tuple, otherwise return err, the original error tuple.
  283. :param test: the test case
  284. :type test: :class:`nose.case.Test`
  285. :param err: sys.exc_info() tuple
  286. :type err: 3-tuple
  287. """
  288. pass
  289. formatFailure._new = True
  290. formatFailure.chainable = True
  291. # test arg is not chainable
  292. formatFailure.static_args = (True, False)
  293. def handleError(self, test, err):
  294. """Called on addError. To handle the error yourself and prevent normal
  295. error processing, return a true value.
  296. :param test: the test case
  297. :type test: :class:`nose.case.Test`
  298. :param err: sys.exc_info() tuple
  299. :type err: 3-tuple
  300. """
  301. pass
  302. handleError._new = True
  303. def handleFailure(self, test, err):
  304. """Called on addFailure. To handle the failure yourself and
  305. prevent normal failure processing, return a true value.
  306. :param test: the test case
  307. :type test: :class:`nose.case.Test`
  308. :param err: sys.exc_info() tuple
  309. :type err: 3-tuple
  310. """
  311. pass
  312. handleFailure._new = True
  313. def loadTestsFromDir(self, path):
  314. """Return iterable of tests from a directory. May be a
  315. generator. Each item returned must be a runnable
  316. unittest.TestCase (or subclass) instance or suite instance.
  317. Return None if your plugin cannot collect any tests from
  318. directory.
  319. :param path: The path to the directory.
  320. """
  321. pass
  322. loadTestsFromDir.generative = True
  323. loadTestsFromDir._new = True
  324. def loadTestsFromModule(self, module, path=None):
  325. """Return iterable of tests in a module. May be a
  326. generator. Each item returned must be a runnable
  327. unittest.TestCase (or subclass) instance.
  328. Return None if your plugin cannot
  329. collect any tests from module.
  330. :param module: The module object
  331. :type module: python module
  332. :param path: the path of the module to search, to distinguish from
  333. namespace package modules
  334. .. note::
  335. NEW. The ``path`` parameter will only be passed by nose 0.11
  336. or above.
  337. """
  338. pass
  339. loadTestsFromModule.generative = True
  340. def loadTestsFromName(self, name, module=None, importPath=None):
  341. """Return tests in this file or module. Return None if you are not able
  342. to load any tests, or an iterable if you are. May be a
  343. generator.
  344. :param name: The test name. May be a file or module name plus a test
  345. callable. Use split_test_name to split into parts. Or it might
  346. be some crazy name of your own devising, in which case, do
  347. whatever you want.
  348. :param module: Module from which the name is to be loaded
  349. :param importPath: Path from which file (must be a python module) was
  350. found
  351. .. warning:: DEPRECATED: this argument will NOT be passed.
  352. """
  353. pass
  354. loadTestsFromName.generative = True
  355. def loadTestsFromNames(self, names, module=None):
  356. """Return a tuple of (tests loaded, remaining names). Return
  357. None if you are not able to load any tests. Multiple plugins
  358. may implement loadTestsFromNames; the remaining name list from
  359. each will be passed to the next as input.
  360. :param names: List of test names.
  361. :type names: iterable
  362. :param module: Module from which the names are to be loaded
  363. """
  364. pass
  365. loadTestsFromNames._new = True
  366. loadTestsFromNames.chainable = True
  367. def loadTestsFromFile(self, filename):
  368. """Return tests in this file. Return None if you are not
  369. interested in loading any tests, or an iterable if you are and
  370. can load some. May be a generator. *If you are interested in
  371. loading tests from the file and encounter no errors, but find
  372. no tests, yield False or return [False].*
  373. .. Note:: This method replaces loadTestsFromPath from the 0.9
  374. API.
  375. :param filename: The full path to the file or directory.
  376. """
  377. pass
  378. loadTestsFromFile.generative = True
  379. loadTestsFromFile._new = True
  380. def loadTestsFromPath(self, path):
  381. """
  382. .. warning:: DEPRECATED -- use loadTestsFromFile instead
  383. """
  384. pass
  385. loadTestsFromPath.deprecated = True
  386. def loadTestsFromTestCase(self, cls):
  387. """Return tests in this test case class. Return None if you are
  388. not able to load any tests, or an iterable if you are. May be a
  389. generator.
  390. :param cls: The test case class. Must be subclass of
  391. :class:`unittest.TestCase`.
  392. """
  393. pass
  394. loadTestsFromTestCase.generative = True
  395. def loadTestsFromTestClass(self, cls):
  396. """Return tests in this test class. Class will *not* be a
  397. unittest.TestCase subclass. Return None if you are not able to
  398. load any tests, an iterable if you are. May be a generator.
  399. :param cls: The test case class. Must be **not** be subclass of
  400. :class:`unittest.TestCase`.
  401. """
  402. pass
  403. loadTestsFromTestClass._new = True
  404. loadTestsFromTestClass.generative = True
  405. def makeTest(self, obj, parent):
  406. """Given an object and its parent, return or yield one or more
  407. test cases. Each test must be a unittest.TestCase (or subclass)
  408. instance. This is called before default test loading to allow
  409. plugins to load an alternate test case or cases for an
  410. object. May be a generator.
  411. :param obj: The object to be made into a test
  412. :param parent: The parent of obj (eg, for a method, the class)
  413. """
  414. pass
  415. makeTest._new = True
  416. makeTest.generative = True
  417. def options(self, parser, env):
  418. """Called to allow plugin to register command line
  419. options with the parser.
  420. DO NOT return a value from this method unless you want to stop
  421. all other plugins from setting their options.
  422. :param parser: options parser instance
  423. :type parser: :class:`ConfigParser.ConfigParser`
  424. :param env: environment, default is os.environ
  425. """
  426. pass
  427. options._new = True
  428. def prepareTest(self, test):
  429. """Called before the test is run by the test runner. Please
  430. note the article *the* in the previous sentence: prepareTest
  431. is called *only once*, and is passed the test case or test
  432. suite that the test runner will execute. It is *not* called
  433. for each individual test case. If you return a non-None value,
  434. that return value will be run as the test. Use this hook to
  435. wrap or decorate the test with another function. If you need
  436. to modify or wrap individual test cases, use `prepareTestCase`
  437. instead.
  438. :param test: the test case
  439. :type test: :class:`nose.case.Test`
  440. """
  441. pass
  442. def prepareTestCase(self, test):
  443. """Prepare or wrap an individual test case. Called before
  444. execution of the test. The test passed here is a
  445. nose.case.Test instance; the case to be executed is in the
  446. test attribute of the passed case. To modify the test to be
  447. run, you should return a callable that takes one argument (the
  448. test result object) -- it is recommended that you *do not*
  449. side-effect the nose.case.Test instance you have been passed.
  450. Keep in mind that when you replace the test callable you are
  451. replacing the run() method of the test case -- including the
  452. exception handling and result calls, etc.
  453. :param test: the test case
  454. :type test: :class:`nose.case.Test`
  455. """
  456. pass
  457. prepareTestCase._new = True
  458. def prepareTestLoader(self, loader):
  459. """Called before tests are loaded. To replace the test loader,
  460. return a test loader. To allow other plugins to process the
  461. test loader, return None. Only one plugin may replace the test
  462. loader. Only valid when using nose.TestProgram.
  463. :param loader: :class:`nose.loader.TestLoader`
  464. (or other loader) instance
  465. """
  466. pass
  467. prepareTestLoader._new = True
  468. def prepareTestResult(self, result):
  469. """Called before the first test is run. To use a different
  470. test result handler for all tests than the given result,
  471. return a test result handler. NOTE however that this handler
  472. will only be seen by tests, that is, inside of the result
  473. proxy system. The TestRunner and TestProgram -- whether nose's
  474. or other -- will continue to see the original result
  475. handler. For this reason, it is usually better to monkeypatch
  476. the result (for instance, if you want to handle some
  477. exceptions in a unique way). Only one plugin may replace the
  478. result, but many may monkeypatch it. If you want to
  479. monkeypatch and stop other plugins from doing so, monkeypatch
  480. and return the patched result.
  481. :param result: :class:`nose.result.TextTestResult`
  482. (or other result) instance
  483. """
  484. pass
  485. prepareTestResult._new = True
  486. def prepareTestRunner(self, runner):
  487. """Called before tests are run. To replace the test runner,
  488. return a test runner. To allow other plugins to process the
  489. test runner, return None. Only valid when using nose.TestProgram.
  490. :param runner: :class:`nose.core.TextTestRunner`
  491. (or other runner) instance
  492. """
  493. pass
  494. prepareTestRunner._new = True
  495. def report(self, stream):
  496. """Called after all error output has been printed. Print your
  497. plugin's report to the provided stream. Return None to allow
  498. other plugins to print reports, any other value to stop them.
  499. :param stream: stream object; send your output here
  500. :type stream: file-like object
  501. """
  502. pass
  503. def setOutputStream(self, stream):
  504. """Called before test output begins. To direct test output to a
  505. new stream, return a stream object, which must implement a
  506. `write(msg)` method. If you only want to note the stream, not
  507. capture or redirect it, then return None.
  508. :param stream: stream object; send your output here
  509. :type stream: file-like object
  510. """
  511. def startContext(self, context):
  512. """Called before context setup and the running of tests in the
  513. context. Note that tests have already been *loaded* from the
  514. context before this call.
  515. :param context: the context about to be setup. May be a module or
  516. class, or any other object that contains tests.
  517. """
  518. pass
  519. startContext._new = True
  520. def startTest(self, test):
  521. """Called before each test is run. DO NOT return a value unless
  522. you want to stop other plugins from seeing the test start.
  523. :param test: the test case
  524. :type test: :class:`nose.case.Test`
  525. """
  526. pass
  527. def stopContext(self, context):
  528. """Called after the tests in a context have run and the
  529. context has been torn down.
  530. :param context: the context that has been torn down. May be a module or
  531. class, or any other object that contains tests.
  532. """
  533. pass
  534. stopContext._new = True
  535. def stopTest(self, test):
  536. """Called after each test is run. DO NOT return a value unless
  537. you want to stop other plugins from seeing that the test has stopped.
  538. :param test: the test case
  539. :type test: :class:`nose.case.Test`
  540. """
  541. pass
  542. def testName(self, test):
  543. """Return a short test name. Called by `nose.case.Test.__str__`.
  544. :param test: the test case
  545. :type test: :class:`nose.case.Test`
  546. """
  547. pass
  548. testName._new = True
  549. def wantClass(self, cls):
  550. """Return true if you want the main test selector to collect
  551. tests from this class, false if you don't, and None if you don't
  552. care.
  553. :param cls: The class being examined by the selector
  554. """
  555. pass
  556. def wantDirectory(self, dirname):
  557. """Return true if you want test collection to descend into this
  558. directory, false if you do not, and None if you don't care.
  559. :param dirname: Full path to directory being examined by the selector
  560. """
  561. pass
  562. def wantFile(self, file):
  563. """Return true if you want to collect tests from this file,
  564. false if you do not and None if you don't care.
  565. Change from 0.9: The optional package parameter is no longer passed.
  566. :param file: Full path to file being examined by the selector
  567. """
  568. pass
  569. def wantFunction(self, function):
  570. """Return true to collect this function as a test, false to
  571. prevent it from being collected, and None if you don't care.
  572. :param function: The function object being examined by the selector
  573. """
  574. pass
  575. def wantMethod(self, method):
  576. """Return true to collect this method as a test, false to
  577. prevent it from being collected, and None if you don't care.
  578. :param method: The method object being examined by the selector
  579. :type method: unbound method
  580. """
  581. pass
  582. def wantModule(self, module):
  583. """Return true if you want to collection to descend into this
  584. module, false to prevent the collector from descending into the
  585. module, and None if you don't care.
  586. :param module: The module object being examined by the selector
  587. :type module: python module
  588. """
  589. pass
  590. def wantModuleTests(self, module):
  591. """
  592. .. warning:: DEPRECATED -- this method will not be called, it has
  593. been folded into wantModule.
  594. """
  595. pass
  596. wantModuleTests.deprecated = True