Merge lp:~lifeless/testresources/bug-284125 into lp:~testresources-developers/testresources/trunk

Proposed by Robert Collins
Status: Merged
Merged at revision: not available
Proposed branch: lp:~lifeless/testresources/bug-284125
Merge into: lp:~testresources-developers/testresources/trunk
Diff against target: None lines
To merge this branch: bzr merge lp:~lifeless/testresources/bug-284125
Reviewer Review Type Date Requested Status
Jonathan Lange Approve
James Henstridge (community) Needs Fixing
testresources developers Pending
Review via email: mp+7543@code.launchpad.net
To post a comment you must log in.
Revision history for this message
James Henstridge (jamesh) wrote :

I'm not sure of the exact uses Jonathan had for this API, but this does not look like what I'd have expected.

To turn on tracing with this API, it looks like I'd have to look through the entire test suite to find out where all the resource manages get instantiated and change the constructors. I'd have expected something closer to slotting in a different TestResult implementation into the test runner: something that can be done in one place and affects all resources. I'm not sure about the best way to do this though.

Second, it would be better to pass the TestResource instance and event type to the tracer rather than a formatted string. This would make it easier to do things like collect statistics about resource use and give the tracer a choice about how to format things.

Lastly, it might be worth adding a trace point before and after making/cleaning a resource. That would allow using the tracer API to calculate how much time those tasks are taking per-run and overall.

review: Needs Fixing
Revision history for this message
Robert Collins (lifeless) wrote :

On Thu, 2009-06-18 at 09:50 +0000, James Henstridge wrote:
>
> I'm not sure of the exact uses Jonathan had for this API, but this
> does not look like what I'd have expected.
>
> To turn on tracing with this API, it looks like I'd have to look
> through the entire test suite to find out where all the resource
> manages get instantiated and change the constructors. I'd have
> expected something closer to slotting in a different TestResult
> implementation into the test runner: something that can be done in one
> place and affects all resources. I'm not sure about the best way to
> do this though.

Neither am I; I felt it was a good idea to get something up and running
to meet the need. Currently there are three points this could be set:
TestResource
OptimisingTestSuite
ResourcedTestCase

Of those:
- RTC is constructed by test discovery and is not positioned to set
state early enough.
- OTS can be got at more easily, but won't suffice if its not being
used.

which leaves TestResource. It can either take a parameter or use global
state. I have a very strong aversion to global state.

So while I agree with the sentiment about how to turn this on, I don't
have any better ideas that will work and be robust.

> Second, it would be better to pass the TestResource instance and event
> type to the tracer rather than a formatted string. This would make it
> easier to do things like collect statistics about resource use and
> give the tracer a choice about how to format things.
>
> Lastly, it might be worth adding a trace point before and after
> making/cleaning a resource. That would allow using the tracer API to
> calculate how much time those tasks are taking per-run and overall.

I will admit to having gone on the 'easiest' approach here; but sure I
can change it to send two parameters.

-Rob

36. By Robert Collins

Merge and simply James Henstridge's reset patch.

Revision history for this message
Robert Collins (lifeless) wrote :

I've pushed a new commit that sends structured data and surrounds the operations.

I don't have any ideas vis-a-vis easy setup of this, so if noone else does I suggest landing it now as that could always be added later.

Revision history for this message
Jonathan Lange (jml) wrote :

In the bug report, you suggest that "we could extend the protocol more deeply and say that we'll emite to the TestResult object being used, IFF it supports an additional function[s] for recording TestResources." I think I like that approach.

However, I think you're right when you suggest that we land this now and incorporate better ideas when we actually have them.

It seems that the docstring for 'trace_function' is out of date. It says "A callable that takes strings to output." However your patch currently calls it with operation, phase & resource manager. Please update the docstring before landing the patch.

review: Approve
37. By Robert Collins

Review feedback.

38. By Robert Collins

Merge support for trace_functions in TestResource.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'NEWS'
--- NEWS 2009-06-17 10:23:42 +0000
+++ NEWS 2009-06-17 12:01:49 +0000
@@ -21,6 +21,10 @@
2121
22 * Started keeping a NEWS file! (Jonathan Lange)22 * Started keeping a NEWS file! (Jonathan Lange)
2323
24 * A trace_function can be supplied when constructing TestResource objects,
25 to allow debugging of when resources are made/cleaned. (Robert Collins,
26 #284125)
27
24 BUG FIXES:28 BUG FIXES:
2529
26 * Calling getResource on a dirty resource now triggers a clean and re-make30 * Calling getResource on a dirty resource now triggers a clean and re-make
2731
=== modified file 'lib/testresources/__init__.py'
--- lib/testresources/__init__.py 2009-06-17 10:23:42 +0000
+++ lib/testresources/__init__.py 2009-06-17 12:01:49 +0000
@@ -197,14 +197,22 @@
197 setUpCost = 1197 setUpCost = 1
198 tearDownCost = 1198 tearDownCost = 1
199199
200 def __init__(self):200 def __init__(self, trace_function=None):
201 """Create a TestResource object.
202
203 :param trace_function: A callable that takes strings to output. This
204 will be called with trace messages when the resource is made and
205 cleaned.
206 """
201 self._dirty = False207 self._dirty = False
202 self._uses = 0208 self._uses = 0
203 self._currentResource = None209 self._currentResource = None
204 self.resources = list(getattr(self.__class__, "resources", []))210 self.resources = list(getattr(self.__class__, "resources", []))
211 self._trace = trace_function or (lambda x:"")
205212
206 def clean_all(self, resource):213 def _clean_all(self, resource):
207 """Clean the dependencies from resource, and then resource itself."""214 """Clean the dependencies from resource, and then resource itself."""
215 self._trace("clean: %s\n" % self)
208 self.clean(resource)216 self.clean(resource)
209 for name, manager in self.resources:217 for name, manager in self.resources:
210 manager.finishedWith(getattr(resource, name))218 manager.finishedWith(getattr(resource, name))
@@ -233,7 +241,7 @@
233 """241 """
234 self._uses -= 1242 self._uses -= 1
235 if self._uses == 0:243 if self._uses == 0:
236 self.clean_all(resource)244 self._clean_all(resource)
237 self._setResource(None)245 self._setResource(None)
238246
239 def getResource(self):247 def getResource(self):
@@ -245,7 +253,7 @@
245 that it is no longer needed.253 that it is no longer needed.
246 """254 """
247 if self._uses == 0:255 if self._uses == 0:
248 self._setResource(self.make_all())256 self._setResource(self._make_all())
249 elif self.isDirty():257 elif self.isDirty():
250 self._resetResource(self._currentResource)258 self._resetResource(self._currentResource)
251 self._uses += 1259 self._uses += 1
@@ -269,8 +277,9 @@
269 finally:277 finally:
270 mgr.finishedWith(res)278 mgr.finishedWith(res)
271279
272 def make_all(self):280 def _make_all(self):
273 """Make the dependencies of this resource and this resource."""281 """Make the dependencies of this resource and this resource."""
282 self._trace("make: %s\n" % self)
274 dependency_resources = {}283 dependency_resources = {}
275 for name, resource in self.resources:284 for name, resource in self.resources:
276 dependency_resources[name] = resource.getResource()285 dependency_resources[name] = resource.getResource()
@@ -306,8 +315,8 @@
306 return result315 return result
307316
308 def _resetResource(self, old_resource):317 def _resetResource(self, old_resource):
309 self.clean_all(old_resource)318 self._clean_all(old_resource)
310 self._setResource(self.make_all())319 self._setResource(self._make_all())
311320
312 def _setResource(self, new_resource):321 def _setResource(self, new_resource):
313 """Set the current resource to a new value."""322 """Set the current resource to a new value."""
314323
=== modified file 'lib/testresources/tests/test_test_resource.py'
--- lib/testresources/tests/test_test_resource.py 2009-06-17 10:23:42 +0000
+++ lib/testresources/tests/test_test_resource.py 2009-06-17 12:01:49 +0000
@@ -44,8 +44,8 @@
44class MockResource(testresources.TestResource):44class MockResource(testresources.TestResource):
45 """Mock resource that logs the number of make and clean calls."""45 """Mock resource that logs the number of make and clean calls."""
4646
47 def __init__(self):47 def __init__(self, trace_function=None):
48 testresources.TestResource.__init__(self)48 testresources.TestResource.__init__(self, trace_function=trace_function)
49 self.makes = 049 self.makes = 0
50 self.cleans = 050 self.cleans = 0
5151
@@ -275,3 +275,13 @@
275 self.assertEqual(1, resource_manager.makes)275 self.assertEqual(1, resource_manager.makes)
276 resource = resource_manager.getResource()276 resource = resource_manager.getResource()
277 self.assertEqual(2, resource_manager.makes)277 self.assertEqual(2, resource_manager.makes)
278
279 def testTraceFunction(self):
280 output = []
281 resource_manager = MockResource(trace_function=output.append)
282 expected = ["make: %s\n" % resource_manager]
283 r = resource_manager.getResource()
284 self.assertEqual(expected, output)
285 expected.append("clean: %s\n" % resource_manager)
286 resource_manager.finishedWith(r)
287 self.assertEqual(expected, output)

Subscribers

People subscribed via source and target branches