~landscape/zope3/ztk-1.1.3

« back to all changes in this revision

Viewing changes to src/zope/testing/testrunner/testrunner-layers-api.txt

  • Committer: Thomas Hervé
  • Date: 2009-09-21 16:46:07 UTC
  • Revision ID: thomas@canonical.com-20090921164607-sky3xhlt02ji80ka
Revert r8: regression with test failures

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
Layers
2
 
======
3
 
 
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.
8
 
 
9
 
Layers are generally implemented as classes using class methods.
10
 
 
11
 
>>> class BaseLayer:
12
 
...     def setUp(cls):
13
 
...         log('BaseLayer.setUp')
14
 
...     setUp = classmethod(setUp)
15
 
...
16
 
...     def tearDown(cls):
17
 
...         log('BaseLayer.tearDown')
18
 
...     tearDown = classmethod(tearDown)
19
 
...
20
 
...     def testSetUp(cls):
21
 
...         log('BaseLayer.testSetUp')
22
 
...     testSetUp = classmethod(testSetUp)
23
 
...
24
 
...     def testTearDown(cls):
25
 
...         log('BaseLayer.testTearDown')
26
 
...     testTearDown = classmethod(testTearDown)
27
 
...
28
 
 
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.
32
 
 
33
 
>>> class TopLayer(BaseLayer):
34
 
...     def setUp(cls):
35
 
...         log('TopLayer.setUp')
36
 
...     setUp = classmethod(setUp)
37
 
...
38
 
...     def tearDown(cls):
39
 
...         log('TopLayer.tearDown')
40
 
...     tearDown = classmethod(tearDown)
41
 
...
42
 
...     def testSetUp(cls):
43
 
...         log('TopLayer.testSetUp')
44
 
...     testSetUp = classmethod(testSetUp)
45
 
...
46
 
...     def testTearDown(cls):
47
 
...         log('TopLayer.testTearDown')
48
 
...     testTearDown = classmethod(testTearDown)
49
 
...
50
 
 
51
 
Tests or test suites specify what layer they need by storing a reference
52
 
in the 'layer' attribute.
53
 
 
54
 
>>> import unittest
55
 
>>> class TestSpecifyingBaseLayer(unittest.TestCase):
56
 
...     'This TestCase explicitly specifies its layer'
57
 
...     layer = BaseLayer
58
 
...     name = 'TestSpecifyingBaseLayer' # For testing only
59
 
...
60
 
...     def setUp(self):
61
 
...         log('TestSpecifyingBaseLayer.setUp')
62
 
...
63
 
...     def tearDown(self):
64
 
...         log('TestSpecifyingBaseLayer.tearDown')
65
 
...
66
 
...     def test1(self):
67
 
...         log('TestSpecifyingBaseLayer.test1')
68
 
...
69
 
...     def test2(self):
70
 
...         log('TestSpecifyingBaseLayer.test2')
71
 
...
72
 
>>> class TestSpecifyingNoLayer(unittest.TestCase):
73
 
...     'This TestCase specifies no layer'
74
 
...     name = 'TestSpecifyingNoLayer' # For testing only
75
 
...     def setUp(self):
76
 
...         log('TestSpecifyingNoLayer.setUp')
77
 
...
78
 
...     def tearDown(self):
79
 
...         log('TestSpecifyingNoLayer.tearDown')
80
 
...
81
 
...     def test1(self):
82
 
...         log('TestSpecifyingNoLayer.test')
83
 
...
84
 
...     def test2(self):
85
 
...         log('TestSpecifyingNoLayer.test')
86
 
...
87
 
 
88
 
Create a TestSuite containing two test suites, one for each of
89
 
TestSpecifyingBaseLayer and TestSpecifyingNoLayer.
90
 
 
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)
95
 
 
96
 
Before we can run the tests, we need to setup some helpers.
97
 
 
98
 
>>> from zope.testing.testrunner import options
99
 
>>> from zope.testing.loggingsupport import InstalledHandler
100
 
>>> import logging
101
 
>>> log_handler = InstalledHandler('zope.testing.tests')
102
 
>>> def log(msg):
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
108
 
...     return opts
109
 
 
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.
113
 
 
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.
127
 
 
128
 
 
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.
132
 
 
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.
141
 
 
142
 
Clear our logged output, as we want to inspect it shortly.
143
 
 
144
 
>>> log_handler.clear()
145
 
 
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.
151
 
 
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.
165
 
 
166
 
 
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.
171
 
 
172
 
>>> def report():
173
 
...     for record in log_handler.records:
174
 
...         print record.getMessage()
175
 
>>> report()
176
 
BaseLayer.setUp
177
 
BaseLayer.testSetUp
178
 
TestSpecifyingBaseLayer.setUp
179
 
TestSpecifyingBaseLayer.test1
180
 
TestSpecifyingBaseLayer.tearDown
181
 
BaseLayer.testTearDown
182
 
BaseLayer.testSetUp
183
 
TestSpecifyingBaseLayer.setUp
184
 
TestSpecifyingBaseLayer.test2
185
 
TestSpecifyingBaseLayer.tearDown
186
 
BaseLayer.testTearDown
187
 
TopLayer.setUp
188
 
BaseLayer.testSetUp
189
 
TopLayer.testSetUp
190
 
TestSpecifyingNoLayer.setUp
191
 
TestSpecifyingNoLayer.test
192
 
TestSpecifyingNoLayer.tearDown
193
 
TopLayer.testTearDown
194
 
BaseLayer.testTearDown
195
 
BaseLayer.testSetUp
196
 
TopLayer.testSetUp
197
 
TestSpecifyingNoLayer.setUp
198
 
TestSpecifyingNoLayer.test
199
 
TestSpecifyingNoLayer.tearDown
200
 
TopLayer.testTearDown
201
 
BaseLayer.testTearDown
202
 
TopLayer.tearDown
203
 
BaseLayer.tearDown
204
 
 
205
 
Now lets stack a few more layers to ensure that our setUp and tearDown
206
 
methods are called in the correct order.
207
 
 
208
 
>>> from zope.testing.testrunner.find import name_from_layer
209
 
>>> class A(object):
210
 
...     def setUp(cls):
211
 
...         log('%s.setUp' % name_from_layer(cls))
212
 
...     setUp = classmethod(setUp)
213
 
...
214
 
...     def tearDown(cls):
215
 
...         log('%s.tearDown' % name_from_layer(cls))
216
 
...     tearDown = classmethod(tearDown)
217
 
...
218
 
...     def testSetUp(cls):
219
 
...         log('%s.testSetUp' % name_from_layer(cls))
220
 
...     testSetUp = classmethod(testSetUp)
221
 
...
222
 
...     def testTearDown(cls):
223
 
...         log('%s.testTearDown' % name_from_layer(cls))
224
 
...     testTearDown = classmethod(testTearDown)
225
 
...         
226
 
>>> class B(A): pass
227
 
>>> class C(B): pass
228
 
>>> class D(A): pass
229
 
>>> class E(D): pass
230
 
>>> class F(C,E): pass
231
 
 
232
 
>>> class DeepTest(unittest.TestCase):
233
 
...     layer = F
234
 
...     def test(self):
235
 
...         pass
236
 
>>> suite = unittest.makeSuite(DeepTest)
237
 
>>> log_handler.clear()
238
 
>>> runner = Runner(options=fresh_options(), args=[], found_suites=[suite])
239
 
>>> succeeded = runner.run()
240
 
Running F tests:
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.
255
 
 
256
 
 
257
 
>>> report()
258
 
A.setUp
259
 
B.setUp
260
 
C.setUp
261
 
D.setUp
262
 
E.setUp
263
 
F.setUp
264
 
A.testSetUp
265
 
B.testSetUp
266
 
C.testSetUp
267
 
D.testSetUp
268
 
E.testSetUp
269
 
F.testSetUp
270
 
F.testTearDown
271
 
E.testTearDown
272
 
D.testTearDown
273
 
C.testTearDown
274
 
B.testTearDown
275
 
A.testTearDown
276
 
F.tearDown
277
 
E.tearDown
278
 
D.tearDown
279
 
C.tearDown
280
 
B.tearDown
281
 
A.tearDown