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