4
A Layer is an object providing setup and teardown methods used to setup
5
and teardown the environment provided by the layer. It may also provide
6
setup and teardown methods used to reset the environment provided by the
7
layer between each test.
9
Layers are generally implemented as classes using class methods.
13
... log('BaseLayer.setUp')
14
... setUp = classmethod(setUp)
16
... def tearDown(cls):
17
... log('BaseLayer.tearDown')
18
... tearDown = classmethod(tearDown)
20
... def testSetUp(cls):
21
... log('BaseLayer.testSetUp')
22
... testSetUp = classmethod(testSetUp)
24
... def testTearDown(cls):
25
... log('BaseLayer.testTearDown')
26
... testTearDown = classmethod(testTearDown)
29
Layers can extend other layers. Note that they do not explicitly
30
invoke the setup and teardown methods of other layers - the test runner
31
does this for us in order to minimize the number of invocations.
33
>>> class TopLayer(BaseLayer):
35
... log('TopLayer.setUp')
36
... setUp = classmethod(setUp)
38
... def tearDown(cls):
39
... log('TopLayer.tearDown')
40
... tearDown = classmethod(tearDown)
42
... def testSetUp(cls):
43
... log('TopLayer.testSetUp')
44
... testSetUp = classmethod(testSetUp)
46
... def testTearDown(cls):
47
... log('TopLayer.testTearDown')
48
... testTearDown = classmethod(testTearDown)
51
Tests or test suites specify what layer they need by storing a reference
52
in the 'layer' attribute.
55
>>> class TestSpecifyingBaseLayer(unittest.TestCase):
56
... 'This TestCase explicitly specifies its layer'
58
... name = 'TestSpecifyingBaseLayer' # For testing only
61
... log('TestSpecifyingBaseLayer.setUp')
63
... def tearDown(self):
64
... log('TestSpecifyingBaseLayer.tearDown')
67
... log('TestSpecifyingBaseLayer.test1')
70
... log('TestSpecifyingBaseLayer.test2')
72
>>> class TestSpecifyingNoLayer(unittest.TestCase):
73
... 'This TestCase specifies no layer'
74
... name = 'TestSpecifyingNoLayer' # For testing only
76
... log('TestSpecifyingNoLayer.setUp')
78
... def tearDown(self):
79
... log('TestSpecifyingNoLayer.tearDown')
82
... log('TestSpecifyingNoLayer.test')
85
... log('TestSpecifyingNoLayer.test')
88
Create a TestSuite containing two test suites, one for each of
89
TestSpecifyingBaseLayer and TestSpecifyingNoLayer.
91
>>> umbrella_suite = unittest.TestSuite()
92
>>> umbrella_suite.addTest(unittest.makeSuite(TestSpecifyingBaseLayer))
93
>>> no_layer_suite = unittest.makeSuite(TestSpecifyingNoLayer)
94
>>> umbrella_suite.addTest(no_layer_suite)
96
Before we can run the tests, we need to setup some helpers.
98
>>> from zope.testing.testrunner import options
99
>>> from zope.testing.loggingsupport import InstalledHandler
101
>>> log_handler = InstalledHandler('zope.testing.tests')
103
... logging.getLogger('zope.testing.tests').info(msg)
104
>>> def fresh_options():
105
... opts = options.get_options(['--test-filter', '.*'])
106
... opts.resume_layer = None
107
... opts.resume_number = 0
110
Now we run the tests. Note that the BaseLayer was not setup when
111
the TestSpecifyingNoLayer was run and setup/torn down around the
112
TestSpecifyingBaseLayer tests.
114
>>> from zope.testing.testrunner.runner import Runner
115
>>> runner = Runner(options=fresh_options(), args=[], found_suites=[umbrella_suite])
116
>>> succeeded = runner.run()
117
Running BaseLayer tests:
118
Set up BaseLayer in N.NNN seconds.
119
Ran 2 tests with 0 failures and 0 errors in N.NNN seconds.
120
Running zope.testing.testrunner.layer.UnitTests tests:
121
Tear down BaseLayer in N.NNN seconds.
122
Set up zope.testing.testrunner.layer.UnitTests in N.NNN seconds.
123
Ran 2 tests with 0 failures and 0 errors in N.NNN seconds.
124
Tearing down left over layers:
125
Tear down zope.testing.testrunner.layer.UnitTests in N.NNN seconds.
126
Total: 4 tests, 0 failures, 0 errors in N.NNN seconds.
129
Now lets specify a layer in the suite containing TestSpecifyingNoLayer
130
and run the tests again. This demonstrates the other method of specifying
131
a layer. This is generally how you specify what layer doctests need.
133
>>> no_layer_suite.layer = BaseLayer
134
>>> runner = Runner(options=fresh_options(), args=[], found_suites=[umbrella_suite])
135
>>> succeeded = runner.run()
136
Running BaseLayer tests:
137
Set up BaseLayer in N.NNN seconds.
138
Ran 4 tests with 0 failures and 0 errors in N.NNN seconds.
139
Tearing down left over layers:
140
Tear down BaseLayer in N.NNN seconds.
142
Clear our logged output, as we want to inspect it shortly.
144
>>> log_handler.clear()
146
Now lets also specify a layer in the TestSpecifyingNoLayer class and rerun
147
the tests. This demonstrates that the most specific layer is used. It also
148
shows the behavior of nested layers - because TopLayer extends BaseLayer,
149
both the BaseLayer and TopLayer environments are setup when the
150
TestSpecifyingNoLayer tests are run.
152
>>> TestSpecifyingNoLayer.layer = TopLayer
153
>>> runner = Runner(options=fresh_options(), args=[], found_suites=[umbrella_suite])
154
>>> succeeded = runner.run()
155
Running BaseLayer tests:
156
Set up BaseLayer in N.NNN seconds.
157
Ran 2 tests with 0 failures and 0 errors in N.NNN seconds.
158
Running TopLayer tests:
159
Set up TopLayer in N.NNN seconds.
160
Ran 2 tests with 0 failures and 0 errors in N.NNN seconds.
161
Tearing down left over layers:
162
Tear down TopLayer in N.NNN seconds.
163
Tear down BaseLayer in N.NNN seconds.
164
Total: 4 tests, 0 failures, 0 errors in N.NNN seconds.
167
If we inspect our trace of what methods got called in what order, we can
168
see that the layer setup and teardown methods only got called once. We can
169
also see that the layer's test setup and teardown methods got called for
170
each test using that layer in the right order.
173
... for record in log_handler.records:
174
... print record.getMessage()
178
TestSpecifyingBaseLayer.setUp
179
TestSpecifyingBaseLayer.test1
180
TestSpecifyingBaseLayer.tearDown
181
BaseLayer.testTearDown
183
TestSpecifyingBaseLayer.setUp
184
TestSpecifyingBaseLayer.test2
185
TestSpecifyingBaseLayer.tearDown
186
BaseLayer.testTearDown
190
TestSpecifyingNoLayer.setUp
191
TestSpecifyingNoLayer.test
192
TestSpecifyingNoLayer.tearDown
193
TopLayer.testTearDown
194
BaseLayer.testTearDown
197
TestSpecifyingNoLayer.setUp
198
TestSpecifyingNoLayer.test
199
TestSpecifyingNoLayer.tearDown
200
TopLayer.testTearDown
201
BaseLayer.testTearDown
205
Now lets stack a few more layers to ensure that our setUp and tearDown
206
methods are called in the correct order.
208
>>> from zope.testing.testrunner.find import name_from_layer
211
... log('%s.setUp' % name_from_layer(cls))
212
... setUp = classmethod(setUp)
214
... def tearDown(cls):
215
... log('%s.tearDown' % name_from_layer(cls))
216
... tearDown = classmethod(tearDown)
218
... def testSetUp(cls):
219
... log('%s.testSetUp' % name_from_layer(cls))
220
... testSetUp = classmethod(testSetUp)
222
... def testTearDown(cls):
223
... log('%s.testTearDown' % name_from_layer(cls))
224
... testTearDown = classmethod(testTearDown)
230
>>> class F(C,E): pass
232
>>> class DeepTest(unittest.TestCase):
236
>>> suite = unittest.makeSuite(DeepTest)
237
>>> log_handler.clear()
238
>>> runner = Runner(options=fresh_options(), args=[], found_suites=[suite])
239
>>> succeeded = runner.run()
241
Set up A in N.NNN seconds.
242
Set up B in N.NNN seconds.
243
Set up C in N.NNN seconds.
244
Set up D in N.NNN seconds.
245
Set up E in N.NNN seconds.
246
Set up F in N.NNN seconds.
247
Ran 1 tests with 0 failures and 0 errors in N.NNN seconds.
248
Tearing down left over layers:
249
Tear down F in N.NNN seconds.
250
Tear down E in N.NNN seconds.
251
Tear down D in N.NNN seconds.
252
Tear down C in N.NNN seconds.
253
Tear down B in N.NNN seconds.
254
Tear down A in N.NNN seconds.