1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
When Plugins Fail
-----------------
Plugin methods should not fail silently. When a plugin method raises
an exception before or during the execution of a test, the exception
will be wrapped in a :class:`nose.failure.Failure` instance and appear as a
failing test. Exceptions raised at other times, such as in the
preparation phase with ``prepareTestLoader`` or ``prepareTestResult``,
or after a test executes, in ``afterTest`` will stop the entire test
run.
>>> import os
>>> import sys
>>> from nose.plugins import Plugin
>>> from nose.plugins.plugintest import run_buffered as run
Our first test plugins take no command-line arguments and raises
AttributeError in beforeTest and afterTest.
>>> class EnabledPlugin(Plugin):
... """Plugin that takes no command-line arguments"""
...
... enabled = True
...
... def configure(self, options, conf):
... pass
... def options(self, parser, env={}):
... pass
>>> class FailBeforePlugin(EnabledPlugin):
... name = "fail-before"
...
... def beforeTest(self, test):
... raise AttributeError()
>>> class FailAfterPlugin(EnabledPlugin):
... name = "fail-after"
...
... def afterTest(self, test):
... raise AttributeError()
Running tests with the fail-before plugin enabled will result in all
tests failing.
>>> support = os.path.join(os.path.dirname(__file__), 'support')
>>> suitepath = os.path.join(support, 'test_spam.py')
>>> run(argv=['nosetests', suitepath],
... plugins=[FailBeforePlugin()])
EE
======================================================================
ERROR: test_spam.test_spam
----------------------------------------------------------------------
Traceback (most recent call last):
...
AttributeError
<BLANKLINE>
======================================================================
ERROR: test_spam.test_eggs
----------------------------------------------------------------------
Traceback (most recent call last):
...
AttributeError
<BLANKLINE>
----------------------------------------------------------------------
Ran 0 tests in ...s
<BLANKLINE>
FAILED (errors=2)
But with the fail-after plugin, the entire test run will fail.
>>> run(argv=['nosetests', suitepath],
... plugins=[FailAfterPlugin()])
Traceback (most recent call last):
...
AttributeError
Likewise, since the next plugin fails in a preparatory method, outside
of test execution, the entire test run fails when the plugin is used.
>>> class FailPreparationPlugin(EnabledPlugin):
... name = "fail-prepare"
...
... def prepareTestLoader(self, loader):
... raise TypeError("That loader is not my type")
>>> run(argv=['nosetests', suitepath],
... plugins=[FailPreparationPlugin()])
Traceback (most recent call last):
...
TypeError: That loader is not my type
Even AttributeErrors and TypeErrors are not silently suppressed as
they used to be for some generative plugin methods (issue152).
These methods caught TypeError and AttributeError and did not record
the exception, before issue152 was fixed: .loadTestsFromDir(),
.loadTestsFromModule(), .loadTestsFromTestCase(),
loadTestsFromTestClass, and .makeTest(). Now, the exception is
caught, but logged as a Failure.
>>> class FailLoadPlugin(EnabledPlugin):
... name = "fail-load"
...
... def loadTestsFromModule(self, module):
... # we're testing exception handling behaviour during
... # iteration, so be a generator function, without
... # actually yielding any tests
... if False:
... yield None
... raise TypeError("bug in plugin")
>>> run(argv=['nosetests', suitepath],
... plugins=[FailLoadPlugin()])
..E
======================================================================
ERROR: Failure: TypeError (bug in plugin)
----------------------------------------------------------------------
Traceback (most recent call last):
...
TypeError: bug in plugin
<BLANKLINE>
----------------------------------------------------------------------
Ran 3 tests in ...s
<BLANKLINE>
FAILED (errors=1)
Also, before issue152 was resolved, .loadTestsFromFile() and
.loadTestsFromName() didn't catch these errors at all, so the
following test would crash nose:
>>> class FailLoadFromNamePlugin(EnabledPlugin):
... name = "fail-load-from-name"
...
... def loadTestsFromName(self, name, module=None, importPath=None):
... if False:
... yield None
... raise TypeError("bug in plugin")
>>> run(argv=['nosetests', suitepath],
... plugins=[FailLoadFromNamePlugin()])
E
======================================================================
ERROR: Failure: TypeError (bug in plugin)
----------------------------------------------------------------------
Traceback (most recent call last):
...
TypeError: bug in plugin
<BLANKLINE>
----------------------------------------------------------------------
Ran 1 test in ...s
<BLANKLINE>
FAILED (errors=1)
|