1 Running Initialization Code Before the Test Run
2 -----------------------------------------------
4 Many applications, especially those using web frameworks like Pylons_
5 or Django_, can't be tested without first being configured or
6 otherwise initialized. Plugins can fulfill this requirement by
7 implementing :meth:`begin() <nose.plugins.base.IPluginInterface.begin>`.
9 In this example, we'll use a very simple example: a widget class that
10 can't be tested without a configuration.
12 Here's the widget class. It's configured at the class or instance
13 level by setting the ``cfg`` attribute to a dictionary.
15 >>> class ConfigurableWidget(object):
17 ... def can_frobnicate(self):
18 ... return self.cfg.get('can_frobnicate', True)
19 ... def likes_cheese(self):
20 ... return self.cfg.get('likes_cheese', True)
22 The tests verify that the widget's methods can be called without
23 raising any exceptions.
26 >>> class TestConfigurableWidget(unittest.TestCase):
27 ... longMessage = False
29 ... self.widget = ConfigurableWidget()
30 ... def test_can_frobnicate(self):
31 ... """Widgets can frobnicate (or not)"""
32 ... self.widget.can_frobnicate()
33 ... def test_likes_cheese(self):
34 ... """Widgets might like cheese"""
35 ... self.widget.likes_cheese()
36 ... def shortDescription(self): # 2.7 compat
38 ... doc = self._testMethodDoc
39 ... except AttributeError:
41 ... doc = self._TestCase__testMethodDoc
42 ... return doc and doc.split("\n")[0].strip() or None
44 The tests are bundled into a suite that we can pass to the test runner.
47 ... return unittest.TestSuite([
48 ... TestConfigurableWidget('test_can_frobnicate'),
49 ... TestConfigurableWidget('test_likes_cheese')])
51 When we run tests without first configuring the ConfigurableWidget,
56 The function :func:`nose.plugins.plugintest.run` reformats test result
57 output to remove timings, which will vary from run to run, and
58 redirects the output to stdout.
60 >>> from nose.plugins.plugintest import run_buffered as run
64 >>> argv = [__file__, '-v']
65 >>> run(argv=argv, suite=suite()) # doctest: +REPORT_NDIFF
66 Widgets can frobnicate (or not) ... ERROR
67 Widgets might like cheese ... ERROR
69 ======================================================================
70 ERROR: Widgets can frobnicate (or not)
71 ----------------------------------------------------------------------
72 Traceback (most recent call last):
74 AttributeError: 'NoneType' object has no attribute 'get'
76 ======================================================================
77 ERROR: Widgets might like cheese
78 ----------------------------------------------------------------------
79 Traceback (most recent call last):
81 AttributeError: 'NoneType' object has no attribute 'get'
83 ----------------------------------------------------------------------
88 To configure the widget system before running tests, write a plugin
89 that implements :meth:`begin() <nose.plugins.base.IPluginInterface.begin>`
90 and initializes the system with a hard-coded configuration. (Later, we'll
91 write a better plugin that accepts a command-line argument specifying the
94 >>> from nose.plugins import Plugin
95 >>> class ConfiguringPlugin(Plugin):
97 ... def configure(self, options, conf):
100 ... ConfigurableWidget.cfg = {}
102 Now configure and execute a new test run using the plugin, which will
103 inject the hard-coded configuration.
105 >>> run(argv=argv, suite=suite(),
106 ... plugins=[ConfiguringPlugin()]) # doctest: +REPORT_NDIFF
107 Widgets can frobnicate (or not) ... ok
108 Widgets might like cheese ... ok
110 ----------------------------------------------------------------------
115 This time the tests pass, because the widget class is configured.
117 But the ConfiguringPlugin is pretty lame -- the configuration it
118 installs is hard coded. A better plugin would allow the user to
119 specify a configuration file on the command line:
121 >>> class BetterConfiguringPlugin(Plugin):
122 ... def options(self, parser, env={}):
123 ... parser.add_option('--widget-config', action='store',
124 ... dest='widget_config', default=None,
125 ... help='Specify path to widget config file')
126 ... def configure(self, options, conf):
127 ... if options.widget_config:
128 ... self.load_config(options.widget_config)
129 ... self.enabled = True
131 ... ConfigurableWidget.cfg = self.cfg
132 ... def load_config(self, path):
133 ... from ConfigParser import ConfigParser
134 ... p = ConfigParser()
136 ... self.cfg = dict(p.items('DEFAULT'))
138 To use the plugin, we need a config file.
141 >>> cfg_file = os.path.join(os.path.dirname(__file__), 'example.cfg')
142 >>> bytes = open(cfg_file, 'w').write("""\
144 ... can_frobnicate = 1
148 Now we can execute a test run using that configuration, after first
149 resetting the widget system to an unconfigured state.
151 >>> ConfigurableWidget.cfg = None
152 >>> argv = [__file__, '-v', '--widget-config', cfg_file]
153 >>> run(argv=argv, suite=suite(),
154 ... plugins=[BetterConfiguringPlugin()]) # doctest: +REPORT_NDIFF
155 Widgets can frobnicate (or not) ... ok
156 Widgets might like cheese ... ok
158 ----------------------------------------------------------------------
163 .. _Pylons: http://pylonshq.com/
164 .. _Django: http://www.djangoproject.com/