Merge lp:~free.ekanayaka/python-fixtures/reusable-fixture into lp:~python-fixtures/python-fixtures/trunk

Proposed by Free Ekanayaka
Status: Needs review
Proposed branch: lp:~free.ekanayaka/python-fixtures/reusable-fixture
Merge into: lp:~python-fixtures/python-fixtures/trunk
Diff against target: 155 lines (+110/-0)
4 files modified
lib/fixtures/__init__.py (+2/-0)
lib/fixtures/_fixtures/__init__.py (+2/-0)
lib/fixtures/_fixtures/reusable.py (+45/-0)
lib/fixtures/tests/_fixtures/test_reusable.py (+61/-0)
To merge this branch: bzr merge lp:~free.ekanayaka/python-fixtures/reusable-fixture
Reviewer Review Type Date Requested Status
python-fixtures committers Pending
Review via email: mp+171503@code.launchpad.net

Description of the change

This an idea that came out from this MP:

https://code.launchpad.net/~free.ekanayaka/rabbitfixture/non-ephemeral/+merge/171117

you might want to read it for the full background.

In a nutshell: in case an expensive fixture can be re-used across different tests, projects can wrap it with ReusableFixture and have it setup/cleaned-up only once.

I've tried to understand if this could be done somehow with testresources (perhaps with the reset() method), but I couldn't figure that out. Comments are welcome.

To post a comment you must log in.
Revision history for this message
Robert Collins (lifeless) wrote :

Hi, this is interesting.

So, testresources is aimed at this, grab me on IRC and I can debug
what's not working for you. If you're seeing setup/teardowns, you
don't have the optimiser working properly.

That said, we can do this thing you've got here, and I'll give it a
full review this week.

-Rob

Unmerged revisions

68. By Free Ekanayaka

Add ReusableFixture

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/fixtures/__init__.py'
2--- lib/fixtures/__init__.py 2012-12-17 00:35:34 +0000
3+++ lib/fixtures/__init__.py 2013-06-26 10:58:24 +0000
4@@ -56,6 +56,7 @@
5 'PopenFixture',
6 'PythonPackage',
7 'PythonPathEntry',
8+ 'ReusableFixture',
9 'StringStream',
10 'TempDir',
11 'TempHomeDir',
12@@ -85,6 +86,7 @@
13 PopenFixture,
14 PythonPackage,
15 PythonPathEntry,
16+ ReusableFixture,
17 StringStream,
18 TempDir,
19 TempHomeDir,
20
21=== modified file 'lib/fixtures/_fixtures/__init__.py'
22--- lib/fixtures/_fixtures/__init__.py 2012-12-16 12:18:12 +0000
23+++ lib/fixtures/_fixtures/__init__.py 2013-06-26 10:58:24 +0000
24@@ -31,6 +31,7 @@
25 'PopenFixture',
26 'PythonPackage',
27 'PythonPathEntry',
28+ 'ReusableFixture',
29 'StringStream',
30 'TempDir',
31 'TempHomeDir',
32@@ -56,6 +57,7 @@
33 from fixtures._fixtures.packagepath import PackagePathEntry
34 from fixtures._fixtures.pythonpackage import PythonPackage
35 from fixtures._fixtures.pythonpath import PythonPathEntry
36+from fixtures._fixtures.reusable import ReusableFixture
37 from fixtures._fixtures.streams import (
38 ByteStream,
39 DetailStream,
40
41=== added file 'lib/fixtures/_fixtures/reusable.py'
42--- lib/fixtures/_fixtures/reusable.py 1970-01-01 00:00:00 +0000
43+++ lib/fixtures/_fixtures/reusable.py 2013-06-26 10:58:24 +0000
44@@ -0,0 +1,45 @@
45+# fixtures: Fixtures with cleanups for testing and convenience.
46+#
47+# Copyright (c) 2011, Robert Collins <robertc@robertcollins.net>
48+#
49+# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
50+# license at the users choice. A copy of both licenses are available in the
51+# project source as Apache-2.0 and BSD. You may not use this file except in
52+# compliance with one of these two licences.
53+#
54+# Unless required by applicable law or agreed to in writing, software
55+# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
56+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
57+# license you chose for the specific language governing permissions and
58+# limitations under that license.
59+import atexit
60+
61+from fixtures import Fixture
62+
63+
64+__all__ = [
65+ 'ReusableFixture',
66+ ]
67+
68+
69+class ReusableFixture(Fixture):
70+ """Wrap a fixture that can be re-uased, cleaning it up at process exit.
71+
72+ This may save considerable time in set-up and tear-down.
73+ """
74+
75+ def __init__(self, fixture):
76+ """Wrap the given re-usable fixture.
77+
78+ :param fixture: The fixture being wrapped.
79+ """
80+ super(ReusableFixture, self).__init__()
81+ self.fixture = fixture
82+ self.count = 0
83+
84+ def setUp(self):
85+ super(ReusableFixture, self).setUp()
86+ if self.count == 0:
87+ self.fixture.setUp()
88+ atexit.register(self.fixture.cleanUp)
89+ self.count += 1
90
91=== added file 'lib/fixtures/tests/_fixtures/test_reusable.py'
92--- lib/fixtures/tests/_fixtures/test_reusable.py 1970-01-01 00:00:00 +0000
93+++ lib/fixtures/tests/_fixtures/test_reusable.py 2013-06-26 10:58:24 +0000
94@@ -0,0 +1,61 @@
95+# fixtures: Fixtures with cleanups for testing and convenience.
96+#
97+# Copyright (c) 2011, Robert Collins <robertc@robertcollins.net>
98+#
99+# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
100+# license at the users choice. A copy of both licenses are available in the
101+# project source as Apache-2.0 and BSD. You may not use this file except in
102+# compliance with one of these two licences.
103+#
104+# Unless required by applicable law or agreed to in writing, software
105+# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
106+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
107+# license you chose for the specific language governing permissions and
108+# limitations under that license.
109+import sys
110+
111+from testtools import TestCase
112+
113+from fixtures import (
114+ ReusableFixture,
115+ TestWithFixtures,
116+ )
117+
118+
119+class DummyFixture(object):
120+
121+ setups = 0
122+ cleanups = 0
123+
124+ def setUp(self):
125+ self.setups += 1
126+
127+ def cleanUp(self):
128+ self.cleanups += 1
129+
130+
131+class ReusableFixtureTest(TestCase, TestWithFixtures):
132+
133+ def setUp(self):
134+ super(ReusableFixtureTest, self).setUp()
135+
136+ def test_reuse(self):
137+ fixture = ReusableFixture(DummyFixture())
138+
139+ fixture.setUp()
140+ fixture.cleanUp()
141+ self.assertEqual(fixture.fixture.setups, 1)
142+ self.assertEqual(fixture.fixture.cleanups, 0)
143+
144+ fixture.setUp()
145+ fixture.cleanUp()
146+ self.assertEqual(fixture.fixture.setups, 1) # Still one setup
147+ self.assertEqual(fixture.fixture.cleanups, 0) # Still no cleanups
148+
149+ self.assertEqual(fixture.count, 2)
150+
151+ def test_atexit(self):
152+ fixture = ReusableFixture(DummyFixture())
153+ fixture.setUp()
154+ sys.exitfunc()
155+ self.assertEqual(fixture.fixture.cleanups, 1)

Subscribers

People subscribed via source and target branches