3
<title>nose: builtin plugin: isolate</title>
4
<link rel="stylesheet" href="site.css" type="text/css"></link>
9
<p>This document covers nose version <b>0.10.3</b></p>
10
<p>Last update: <b>Tue Jun 3 11:50:26 2008</b></p>
11
<h2>Plugins</h2><ul><li><a href="plugin_attrib.html">Builtin Plugin: attrib</a></li><li><a href="plugin_capture.html">Builtin Plugin: capture</a></li><li><a href="plugin_cover.html">Builtin Plugin: cover</a></li><li><a href="plugin_debug.html">Builtin Plugin: debug</a></li><li><a href="plugin_deprecated.html">Builtin Plugin: deprecated</a></li><li><a href="plugin_doctests.html">Builtin Plugin: doctests</a></li><li><a href="plugin_failuredetail.html">Builtin Plugin: failuredetail</a></li><li><a href="plugin_isolate.html">Builtin Plugin: isolate</a></li><li><a href="plugin_prof.html">Builtin Plugin: prof</a></li><li><a href="plugin_skip.html">Builtin Plugin: skip</a></li><li><a href="plugin_testid.html">Builtin Plugin: testid</a></li><li><a href="error_class_plugin.html">ErrorClass Plugins</a></li><li><a href="plugin_interface.html">Plugin Interface</a></li><li><a href="writing_plugins.html">Writing Plugins</a></li></ul><h2>Modules</h2><ul><li><a href="module_nose.case.html">Module: nose.case</a></li><li><a href="module_nose.commands.html">Module: nose.commands</a></li><li><a href="module_nose.config.html">Module: nose.config</a></li><li><a href="module_nose.core.html">Module: nose.core</a></li><li><a href="module_nose.exc.html">Module: nose.exc</a></li><li><a href="module_nose.failure.html">Module: nose.failure</a></li><li><a href="module_nose.importer.html">Module: nose.importer</a></li><li><a href="module_nose.inspector.html">Module: nose.inspector</a></li><li><a href="module_nose.loader.html">Module: nose.loader</a></li><li><a href="module_nose.plugins.manager.html">Module: nose.plugins.manager</a></li><li><a href="module_nose.plugins.plugintest.html">Module: nose.plugins.plugintest</a></li><li><a href="module_nose.proxy.html">Module: nose.proxy</a></li><li><a href="module_nose.result.html">Module: nose.result</a></li><li><a href="module_nose.selector.html">Module: nose.selector</a></li><li><a href="module_nose.suite.html">Module: nose.suite</a></li><li><a href="module_nose.tools.html">Module: nose.tools</a></li><li><a href="module_nose.twistedtools.html">Module: nose.twistedtools</a></li><li><a href="module_nose.util.html">Module: nose.util</a></li></ul><h2>Plugin Examples</h2><ul><li><a href="unwanted_package.html">Excluding Unwanted Packages</a></li><li><a href="errorclass_failure.html">Failure of Errorclasses</a></li><li><a href="imported_tests.html">Importing Tests</a></li><li><a href="empty_plugin.html">Minimal plugin</a></li><li><a href="restricted_plugin_options.html">Restricted Plugin Managers</a></li><li><a href="init_plugin.html">Running Initialization Code Before the Test Run</a></li><li><a href="selector_plugin.html">Using a Custom Selector</a></li><li><a href="plugin_exceptions.html">When Plugins Fail</a></li><li><a href="plugintest_environment.html">nose.plugins.plugintest, os.environ and sys.argv</a></li></ul>
15
<h1>nose: builtin plugin: isolate</h1>
17
<p>Use the isolation plugin with --with-isolation or the
18
NOSE_WITH_ISOLATION environment variable to clean sys.modules after
19
each test module is loaded and executed.</p>
20
<p>The isolation module is in effect similar to wrapping the following
21
functions around the import and execution of each test module:</p>
22
<pre class="literal-block">
24
module._mods = sys.modules.copy()
27
to_del = [ m for m in sys.modules.keys() if m not in
31
sys.modules.update(module._mods)
33
<p>Isolation works only during lazy loading. In normal use, this is only
34
during discovery of modules within a directory, where the process of
35
importing, loading tests and running tests from each module is
36
encapsulated in a single loadTestsFromName call. This plugin
37
implements loadTestsFromNames to force the same lazy-loading there,
38
which allows isolation to work in directed mode as well as discovery,
39
at the cost of some efficiency: lazy-loading names forces full context
40
setup and teardown to run for each name, defeating the grouping that
41
is normally used to ensure that context setup and teardown are run the
42
fewest possible times for a given set of names.</p>
43
<p>PLEASE NOTE that this plugin should not be used in conjunction with
44
other plugins that assume that modules once imported will stay
45
imported; for instance, it may cause very odd results when used with
46
the coverage plugin.</p>
49
<h2>Plugin Methods Implemented</h2>
51
<p>This plugin implements the following plugin interface methods:</p>
53
<ul><li><a href="plugin_interface.html#afterContext">afterContext</a></li><li><a href="plugin_interface.html#beforeContext">beforeContext</a></li><li><a href="plugin_interface.html#configure">configure</a></li><li><a href="plugin_interface.html#loadTestsFromNames">loadTestsFromNames</a></li><li><a href="plugin_interface.html#options">options</a></li><li><a href="plugin_interface.html#prepareTestLoader">prepareTestLoader</a></li></ul>
56
<h2>Commandline Options</h2>
58
<p>This plugin adds the following commandline options:</p>
61
--with-isolation Enable plugin IsolationPlugin: Activate the isolation
62
plugin to isolate changes to external modules to a single
63
test module or package. The isolation plugin resets the
64
contents of sys.modules after each test module or package
65
runs to its state before the test. PLEASE NOTE that this
66
plugin should not be used with the coverage plugin in any
67
other case where module reloading may produce undesirable
68
side-effects. [NOSE_WITH_ISOLATION]
73
<div class="highlight"><pre><span class="sd">"""Use the isolation plugin with --with-isolation or the</span>
74
<span class="sd">NOSE_WITH_ISOLATION environment variable to clean sys.modules after</span>
75
<span class="sd">each test module is loaded and executed.</span>
77
<span class="sd">The isolation module is in effect similar to wrapping the following</span>
78
<span class="sd">functions around the import and execution of each test module::</span>
80
<span class="sd"> def setup(module):</span>
81
<span class="sd"> module._mods = sys.modules.copy()</span>
82
<span class="sd"> </span>
83
<span class="sd"> def teardown(module):</span>
84
<span class="sd"> to_del = [ m for m in sys.modules.keys() if m not in</span>
85
<span class="sd"> module._mods ]</span>
86
<span class="sd"> for mod in to_del:</span>
87
<span class="sd"> del sys.modules[mod]</span>
88
<span class="sd"> sys.modules.update(module._mods)</span>
90
<span class="sd">Isolation works only during lazy loading. In normal use, this is only</span>
91
<span class="sd">during discovery of modules within a directory, where the process of</span>
92
<span class="sd">importing, loading tests and running tests from each module is</span>
93
<span class="sd">encapsulated in a single loadTestsFromName call. This plugin</span>
94
<span class="sd">implements loadTestsFromNames to force the same lazy-loading there,</span>
95
<span class="sd">which allows isolation to work in directed mode as well as discovery,</span>
96
<span class="sd">at the cost of some efficiency: lazy-loading names forces full context</span>
97
<span class="sd">setup and teardown to run for each name, defeating the grouping that</span>
98
<span class="sd">is normally used to ensure that context setup and teardown are run the</span>
99
<span class="sd">fewest possible times for a given set of names.</span>
101
<span class="sd">PLEASE NOTE that this plugin should not be used in conjunction with</span>
102
<span class="sd">other plugins that assume that modules once imported will stay</span>
103
<span class="sd">imported; for instance, it may cause very odd results when used with</span>
104
<span class="sd">the coverage plugin.</span>
105
<span class="sd">"""</span>
107
<span class="k">import</span> <span class="nn">logging</span>
108
<span class="k">import</span> <span class="nn">sys</span>
110
<span class="k">from</span> <span class="nn">nose.plugins</span> <span class="k">import</span> <span class="n">Plugin</span>
113
<span class="n">log</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="s">'nose.plugins.isolation'</span><span class="p">)</span>
115
<span class="k">class</span> <span class="nc">IsolationPlugin</span><span class="p">(</span><span class="n">Plugin</span><span class="p">):</span>
116
<span class="sd">"""</span>
117
<span class="sd"> Activate the isolation plugin to isolate changes to external</span>
118
<span class="sd"> modules to a single test module or package. The isolation plugin</span>
119
<span class="sd"> resets the contents of sys.modules after each test module or</span>
120
<span class="sd"> package runs to its state before the test. PLEASE NOTE that this</span>
121
<span class="sd"> plugin should not be used with the coverage plugin in any other case</span>
122
<span class="sd"> where module reloading may produce undesirable side-effects.</span>
123
<span class="sd"> """</span>
124
<span class="n">score</span> <span class="o">=</span> <span class="mi">10</span> <span class="c"># I want to be last</span>
125
<span class="n">name</span> <span class="o">=</span> <span class="s">'isolation'</span>
127
<span class="k">def</span> <span class="nf">configure</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">options</span><span class="p">,</span> <span class="n">conf</span><span class="p">):</span>
128
<span class="n">Plugin</span><span class="o">.</span><span class="n">configure</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">options</span><span class="p">,</span> <span class="n">conf</span><span class="p">)</span>
129
<span class="bp">self</span><span class="o">.</span><span class="n">_mod_stack</span> <span class="o">=</span> <span class="p">[]</span>
131
<span class="k">def</span> <span class="nf">beforeContext</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
132
<span class="sd">"""Copy sys.modules onto my mod stack</span>
133
<span class="sd"> """</span>
134
<span class="n">mods</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">modules</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
135
<span class="bp">self</span><span class="o">.</span><span class="n">_mod_stack</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">mods</span><span class="p">)</span>
137
<span class="k">def</span> <span class="nf">afterContext</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
138
<span class="sd">"""Pop my mod stack and restore sys.modules to the state</span>
139
<span class="sd"> it was in when mod stack was pushed.</span>
140
<span class="sd"> """</span>
141
<span class="n">mods</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_mod_stack</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
142
<span class="n">to_del</span> <span class="o">=</span> <span class="p">[</span> <span class="n">m</span> <span class="k">for</span> <span class="n">m</span> <span class="ow">in</span> <span class="n">sys</span><span class="o">.</span><span class="n">modules</span><span class="o">.</span><span class="n">keys</span><span class="p">()</span> <span class="k">if</span> <span class="n">m</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">mods</span> <span class="p">]</span>
143
<span class="k">if</span> <span class="n">to_del</span><span class="p">:</span>
144
<span class="n">log</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">'removing sys modules entries: </span><span class="si">%s</span><span class="s">'</span><span class="p">,</span> <span class="n">to_del</span><span class="p">)</span>
145
<span class="k">for</span> <span class="n">mod</span> <span class="ow">in</span> <span class="n">to_del</span><span class="p">:</span>
146
<span class="k">del</span> <span class="n">sys</span><span class="o">.</span><span class="n">modules</span><span class="p">[</span><span class="n">mod</span><span class="p">]</span>
147
<span class="n">sys</span><span class="o">.</span><span class="n">modules</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">mods</span><span class="p">)</span>
149
<span class="k">def</span> <span class="nf">loadTestsFromNames</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">names</span><span class="p">,</span> <span class="n">module</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
150
<span class="sd">"""Create a lazy suite that calls beforeContext and afterContext</span>
151
<span class="sd"> around each name. The side-effect of this is that full context</span>
152
<span class="sd"> fixtures will be set up and torn down around each test named.</span>
153
<span class="sd"> """</span>
154
<span class="c"># Fast path for when we don't care</span>
155
<span class="k">if</span> <span class="ow">not</span> <span class="n">names</span> <span class="ow">or</span> <span class="nb">len</span><span class="p">(</span><span class="n">names</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
156
<span class="k">return</span>
157
<span class="n">loader</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">loader</span>
158
<span class="n">plugins</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">conf</span><span class="o">.</span><span class="n">plugins</span>
159
<span class="k">def</span> <span class="nf">lazy</span><span class="p">():</span>
160
<span class="k">for</span> <span class="n">name</span> <span class="ow">in</span> <span class="n">names</span><span class="p">:</span>
161
<span class="n">plugins</span><span class="o">.</span><span class="n">beforeContext</span><span class="p">()</span>
162
<span class="k">yield</span> <span class="n">loader</span><span class="o">.</span><span class="n">loadTestsFromName</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">module</span><span class="o">=</span><span class="n">module</span><span class="p">)</span>
163
<span class="n">plugins</span><span class="o">.</span><span class="n">afterContext</span><span class="p">()</span>
164
<span class="k">return</span> <span class="p">(</span><span class="n">loader</span><span class="o">.</span><span class="n">suiteClass</span><span class="p">(</span><span class="n">lazy</span><span class="p">),</span> <span class="p">[])</span>
166
<span class="k">def</span> <span class="nf">prepareTestLoader</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">loader</span><span class="p">):</span>
167
<span class="sd">"""Get handle on test loader so we can use it in loadTestsFromNames.</span>
168
<span class="sd"> """</span>
169
<span class="bp">self</span><span class="o">.</span><span class="n">loader</span> <span class="o">=</span> <span class="n">loader</span>
174
<script src="http://www.google-analytics.com/urchin.js"
175
type="text/javascript">
177
<script type="text/javascript">
178
_uacct = "UA-2236166-1";