This file is indexed.

/usr/share/pyshared/zope/testrunner/testrunner-layers-api.txt is in python-zope.testrunner 4.0.3-3.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
Layers
======

A Layer is an object providing setup and teardown methods used to setup
and teardown the environment provided by the layer. It may also provide
setup and teardown methods used to reset the environment provided by the
layer between each test.

Layers are generally implemented as classes using class methods.

>>> class BaseLayer:
...     def setUp(cls):
...         log('BaseLayer.setUp')
...     setUp = classmethod(setUp)
...
...     def tearDown(cls):
...         log('BaseLayer.tearDown')
...     tearDown = classmethod(tearDown)
...
...     def testSetUp(cls):
...         log('BaseLayer.testSetUp')
...     testSetUp = classmethod(testSetUp)
...
...     def testTearDown(cls):
...         log('BaseLayer.testTearDown')
...     testTearDown = classmethod(testTearDown)
...

Layers can extend other layers. Note that they do not explicitly
invoke the setup and teardown methods of other layers - the test runner
does this for us in order to minimize the number of invocations.

>>> class TopLayer(BaseLayer):
...     def setUp(cls):
...         log('TopLayer.setUp')
...     setUp = classmethod(setUp)
...
...     def tearDown(cls):
...         log('TopLayer.tearDown')
...     tearDown = classmethod(tearDown)
...
...     def testSetUp(cls):
...         log('TopLayer.testSetUp')
...     testSetUp = classmethod(testSetUp)
...
...     def testTearDown(cls):
...         log('TopLayer.testTearDown')
...     testTearDown = classmethod(testTearDown)
...

Tests or test suites specify what layer they need by storing a reference
in the 'layer' attribute.

>>> import unittest
>>> class TestSpecifyingBaseLayer(unittest.TestCase):
...     'This TestCase explicitly specifies its layer'
...     layer = BaseLayer
...     name = 'TestSpecifyingBaseLayer' # For testing only
...
...     def setUp(self):
...         log('TestSpecifyingBaseLayer.setUp')
...
...     def tearDown(self):
...         log('TestSpecifyingBaseLayer.tearDown')
...
...     def test1(self):
...         log('TestSpecifyingBaseLayer.test1')
...
...     def test2(self):
...         log('TestSpecifyingBaseLayer.test2')
...
>>> class TestSpecifyingNoLayer(unittest.TestCase):
...     'This TestCase specifies no layer'
...     name = 'TestSpecifyingNoLayer' # For testing only
...     def setUp(self):
...         log('TestSpecifyingNoLayer.setUp')
...
...     def tearDown(self):
...         log('TestSpecifyingNoLayer.tearDown')
...
...     def test1(self):
...         log('TestSpecifyingNoLayer.test')
...
...     def test2(self):
...         log('TestSpecifyingNoLayer.test')
...

Create a TestSuite containing two test suites, one for each of
TestSpecifyingBaseLayer and TestSpecifyingNoLayer.

>>> umbrella_suite = unittest.TestSuite()
>>> umbrella_suite.addTest(unittest.makeSuite(TestSpecifyingBaseLayer))
>>> no_layer_suite = unittest.makeSuite(TestSpecifyingNoLayer)
>>> umbrella_suite.addTest(no_layer_suite)

Before we can run the tests, we need to setup some helpers.

>>> from zope.testrunner import options
>>> from zope.testing.loggingsupport import InstalledHandler
>>> import logging
>>> log_handler = InstalledHandler('zope.testrunner.tests')
>>> def log(msg):
...     logging.getLogger('zope.testrunner.tests').info(msg)
>>> def fresh_options():
...     opts = options.get_options(['--test-filter', '.*'])
...     opts.resume_layer = None
...     opts.resume_number = 0
...     return opts

Now we run the tests. Note that the BaseLayer was not setup when
the TestSpecifyingNoLayer was run and setup/torn down around the
TestSpecifyingBaseLayer tests.

>>> from zope.testrunner.runner import Runner
>>> runner = Runner(options=fresh_options(), args=[], found_suites=[umbrella_suite])
>>> succeeded = runner.run()
Running ...BaseLayer tests:
  Set up ...BaseLayer in N.NNN seconds.
  Ran 2 tests with 0 failures and 0 errors in N.NNN seconds.
Running zope.testrunner.layer.UnitTests tests:
  Tear down ...BaseLayer in N.NNN seconds.
  Set up zope.testrunner.layer.UnitTests in N.NNN seconds.
  Ran 2 tests with 0 failures and 0 errors in N.NNN seconds.
Tearing down left over layers:
  Tear down zope.testrunner.layer.UnitTests in N.NNN seconds.
Total: 4 tests, 0 failures, 0 errors in N.NNN seconds.


Now lets specify a layer in the suite containing TestSpecifyingNoLayer
and run the tests again. This demonstrates the other method of specifying
a layer. This is generally how you specify what layer doctests need.

>>> no_layer_suite.layer = BaseLayer
>>> runner = Runner(options=fresh_options(), args=[], found_suites=[umbrella_suite])
>>> succeeded = runner.run()
Running ...BaseLayer tests:
  Set up ...BaseLayer in N.NNN seconds.
  Ran 4 tests with 0 failures and 0 errors in N.NNN seconds.
Tearing down left over layers:
  Tear down ...BaseLayer in N.NNN seconds.

Clear our logged output, as we want to inspect it shortly.

>>> log_handler.clear()

Now lets also specify a layer in the TestSpecifyingNoLayer class and rerun
the tests. This demonstrates that the most specific layer is used. It also
shows the behavior of nested layers - because TopLayer extends BaseLayer,
both the BaseLayer and TopLayer environments are setup when the
TestSpecifyingNoLayer tests are run.

>>> TestSpecifyingNoLayer.layer = TopLayer
>>> runner = Runner(options=fresh_options(), args=[], found_suites=[umbrella_suite])
>>> succeeded = runner.run()
Running ...BaseLayer tests:
  Set up ...BaseLayer in N.NNN seconds.
  Ran 2 tests with 0 failures and 0 errors in N.NNN seconds.
Running ...TopLayer tests:
  Set up ...TopLayer in N.NNN seconds.
  Ran 2 tests with 0 failures and 0 errors in N.NNN seconds.
Tearing down left over layers:
  Tear down ...TopLayer in N.NNN seconds.
  Tear down ...BaseLayer in N.NNN seconds.
Total: 4 tests, 0 failures, 0 errors in N.NNN seconds.


If we inspect our trace of what methods got called in what order, we can
see that the layer setup and teardown methods only got called once. We can
also see that the layer's test setup and teardown methods got called for
each test using that layer in the right order.

>>> def report():
...     print "Report:"
...     for record in log_handler.records:
...         print record.getMessage()
>>> report()
Report:
BaseLayer.setUp
BaseLayer.testSetUp
TestSpecifyingBaseLayer.setUp
TestSpecifyingBaseLayer.test1
TestSpecifyingBaseLayer.tearDown
BaseLayer.testTearDown
BaseLayer.testSetUp
TestSpecifyingBaseLayer.setUp
TestSpecifyingBaseLayer.test2
TestSpecifyingBaseLayer.tearDown
BaseLayer.testTearDown
TopLayer.setUp
BaseLayer.testSetUp
TopLayer.testSetUp
TestSpecifyingNoLayer.setUp
TestSpecifyingNoLayer.test
TestSpecifyingNoLayer.tearDown
TopLayer.testTearDown
BaseLayer.testTearDown
BaseLayer.testSetUp
TopLayer.testSetUp
TestSpecifyingNoLayer.setUp
TestSpecifyingNoLayer.test
TestSpecifyingNoLayer.tearDown
TopLayer.testTearDown
BaseLayer.testTearDown
TopLayer.tearDown
BaseLayer.tearDown

Now lets stack a few more layers to ensure that our setUp and tearDown
methods are called in the correct order.

>>> from zope.testrunner.find import name_from_layer
>>> class A(object):
...     def setUp(cls):
...         log('%s.setUp' % name_from_layer(cls))
...     setUp = classmethod(setUp)
...
...     def tearDown(cls):
...         log('%s.tearDown' % name_from_layer(cls))
...     tearDown = classmethod(tearDown)
...
...     def testSetUp(cls):
...         log('%s.testSetUp' % name_from_layer(cls))
...     testSetUp = classmethod(testSetUp)
...
...     def testTearDown(cls):
...         log('%s.testTearDown' % name_from_layer(cls))
...     testTearDown = classmethod(testTearDown)
...         
>>> class B(A): pass
>>> class C(B): pass
>>> class D(A): pass
>>> class E(D): pass
>>> class F(C,E): pass

>>> class DeepTest(unittest.TestCase):
...     layer = F
...     def test(self):
...         pass
>>> suite = unittest.makeSuite(DeepTest)
>>> log_handler.clear()
>>> runner = Runner(options=fresh_options(), args=[], found_suites=[suite])
>>> succeeded = runner.run() #doctest: +ELLIPSIS
Running ...F tests:
  Set up ...A in N.NNN seconds.
  Set up ...B in N.NNN seconds.
  Set up ...C in N.NNN seconds.
  Set up ...D in N.NNN seconds.
  Set up ...E in N.NNN seconds.
  Set up ...F in N.NNN seconds.
  Ran 1 tests with 0 failures and 0 errors in N.NNN seconds.
Tearing down left over layers:
  Tear down ...F in N.NNN seconds.
  Tear down ...E in N.NNN seconds.
  Tear down ...D in N.NNN seconds.
  Tear down ...C in N.NNN seconds.
  Tear down ...B in N.NNN seconds.
  Tear down ...A in N.NNN seconds.


>>> report() #doctest: +ELLIPSIS
Report:
...A.setUp
...B.setUp
...C.setUp
...D.setUp
...E.setUp
...F.setUp
...A.testSetUp
...B.testSetUp
...C.testSetUp
...D.testSetUp
...E.testSetUp
...F.testSetUp
...F.testTearDown
...E.testTearDown
...D.testTearDown
...C.testTearDown
...B.testTearDown
...A.testTearDown
...F.tearDown
...E.tearDown
...D.tearDown
...C.tearDown
...B.tearDown
...A.tearDown