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
=== modified file 'lib/fixtures/__init__.py'
--- lib/fixtures/__init__.py 2012-12-17 00:35:34 +0000
+++ lib/fixtures/__init__.py 2013-06-26 10:58:24 +0000
@@ -56,6 +56,7 @@
56 'PopenFixture',56 'PopenFixture',
57 'PythonPackage',57 'PythonPackage',
58 'PythonPathEntry',58 'PythonPathEntry',
59 'ReusableFixture',
59 'StringStream',60 'StringStream',
60 'TempDir',61 'TempDir',
61 'TempHomeDir',62 'TempHomeDir',
@@ -85,6 +86,7 @@
85 PopenFixture,86 PopenFixture,
86 PythonPackage,87 PythonPackage,
87 PythonPathEntry,88 PythonPathEntry,
89 ReusableFixture,
88 StringStream,90 StringStream,
89 TempDir,91 TempDir,
90 TempHomeDir,92 TempHomeDir,
9193
=== modified file 'lib/fixtures/_fixtures/__init__.py'
--- lib/fixtures/_fixtures/__init__.py 2012-12-16 12:18:12 +0000
+++ lib/fixtures/_fixtures/__init__.py 2013-06-26 10:58:24 +0000
@@ -31,6 +31,7 @@
31 'PopenFixture',31 'PopenFixture',
32 'PythonPackage',32 'PythonPackage',
33 'PythonPathEntry',33 'PythonPathEntry',
34 'ReusableFixture',
34 'StringStream',35 'StringStream',
35 'TempDir',36 'TempDir',
36 'TempHomeDir',37 'TempHomeDir',
@@ -56,6 +57,7 @@
56from fixtures._fixtures.packagepath import PackagePathEntry57from fixtures._fixtures.packagepath import PackagePathEntry
57from fixtures._fixtures.pythonpackage import PythonPackage58from fixtures._fixtures.pythonpackage import PythonPackage
58from fixtures._fixtures.pythonpath import PythonPathEntry59from fixtures._fixtures.pythonpath import PythonPathEntry
60from fixtures._fixtures.reusable import ReusableFixture
59from fixtures._fixtures.streams import (61from fixtures._fixtures.streams import (
60 ByteStream,62 ByteStream,
61 DetailStream,63 DetailStream,
6264
=== added file 'lib/fixtures/_fixtures/reusable.py'
--- lib/fixtures/_fixtures/reusable.py 1970-01-01 00:00:00 +0000
+++ lib/fixtures/_fixtures/reusable.py 2013-06-26 10:58:24 +0000
@@ -0,0 +1,45 @@
1# fixtures: Fixtures with cleanups for testing and convenience.
2#
3# Copyright (c) 2011, Robert Collins <robertc@robertcollins.net>
4#
5# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
6# license at the users choice. A copy of both licenses are available in the
7# project source as Apache-2.0 and BSD. You may not use this file except in
8# compliance with one of these two licences.
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# license you chose for the specific language governing permissions and
14# limitations under that license.
15import atexit
16
17from fixtures import Fixture
18
19
20__all__ = [
21 'ReusableFixture',
22 ]
23
24
25class ReusableFixture(Fixture):
26 """Wrap a fixture that can be re-uased, cleaning it up at process exit.
27
28 This may save considerable time in set-up and tear-down.
29 """
30
31 def __init__(self, fixture):
32 """Wrap the given re-usable fixture.
33
34 :param fixture: The fixture being wrapped.
35 """
36 super(ReusableFixture, self).__init__()
37 self.fixture = fixture
38 self.count = 0
39
40 def setUp(self):
41 super(ReusableFixture, self).setUp()
42 if self.count == 0:
43 self.fixture.setUp()
44 atexit.register(self.fixture.cleanUp)
45 self.count += 1
046
=== added file 'lib/fixtures/tests/_fixtures/test_reusable.py'
--- lib/fixtures/tests/_fixtures/test_reusable.py 1970-01-01 00:00:00 +0000
+++ lib/fixtures/tests/_fixtures/test_reusable.py 2013-06-26 10:58:24 +0000
@@ -0,0 +1,61 @@
1# fixtures: Fixtures with cleanups for testing and convenience.
2#
3# Copyright (c) 2011, Robert Collins <robertc@robertcollins.net>
4#
5# Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
6# license at the users choice. A copy of both licenses are available in the
7# project source as Apache-2.0 and BSD. You may not use this file except in
8# compliance with one of these two licences.
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# license you chose for the specific language governing permissions and
14# limitations under that license.
15import sys
16
17from testtools import TestCase
18
19from fixtures import (
20 ReusableFixture,
21 TestWithFixtures,
22 )
23
24
25class DummyFixture(object):
26
27 setups = 0
28 cleanups = 0
29
30 def setUp(self):
31 self.setups += 1
32
33 def cleanUp(self):
34 self.cleanups += 1
35
36
37class ReusableFixtureTest(TestCase, TestWithFixtures):
38
39 def setUp(self):
40 super(ReusableFixtureTest, self).setUp()
41
42 def test_reuse(self):
43 fixture = ReusableFixture(DummyFixture())
44
45 fixture.setUp()
46 fixture.cleanUp()
47 self.assertEqual(fixture.fixture.setups, 1)
48 self.assertEqual(fixture.fixture.cleanups, 0)
49
50 fixture.setUp()
51 fixture.cleanUp()
52 self.assertEqual(fixture.fixture.setups, 1) # Still one setup
53 self.assertEqual(fixture.fixture.cleanups, 0) # Still no cleanups
54
55 self.assertEqual(fixture.count, 2)
56
57 def test_atexit(self):
58 fixture = ReusableFixture(DummyFixture())
59 fixture.setUp()
60 sys.exitfunc()
61 self.assertEqual(fixture.fixture.cleanups, 1)

Subscribers

People subscribed via source and target branches