Nir Soffer has uploaded a new change for review. Change subject: tests: Add monkey patching class decorator ......................................................................
tests: Add monkey patching class decorator Using the new MonkeyClass decorator, you can do monkey patching during all test methods in a test case class, without implementing setUp() or tearDown(). Change-Id: Ice429b01afaf00730ff59dcdf866ab5eeae6b926 Signed-off-by: Nir Soffer <nsof...@redhat.com> --- M tests/monkeypatch.py M tests/monkeypatchTests.py 2 files changed, 89 insertions(+), 15 deletions(-) git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/75/20175/1 diff --git a/tests/monkeypatch.py b/tests/monkeypatch.py index f851f82..b51f097 100644 --- a/tests/monkeypatch.py +++ b/tests/monkeypatch.py @@ -21,8 +21,9 @@ from contextlib import contextmanager from functools import wraps + # -# Monkey patch +# Monkey patch. # # Usage: # --- @@ -49,8 +50,6 @@ # # using patched functions # --- # - - class Patch(object): def __init__(self, what): @@ -75,7 +74,7 @@ # # Usage: # --- -# from monkeypatch import MonkeyPatch +# from monkeypatch import MonkeyPatchScope # # def test(): # with MonkeyPatchScope([ @@ -96,7 +95,7 @@ # -# Monkey patch decoration. +# Monkey patch function decorator. # # Usage: # --- @@ -116,3 +115,50 @@ return f(*args, **kw) return wrapper return decorator + + +# +# Monkey patch class decorator. +# +# Usage: +# --- +# from monkeypatch import MonkeyClass +# +# @MonkeyClass(subprocess, 'Popen', lambda x: None) +# @MonkeyClass(os, 'chown', lambda *x: 0) +# class TestSomething(): +# +# def testThis(self): +# # using patched functions +# +# def testThat(self): +# # using patched functions +# --- +# +def MonkeyClass(module, name, that): + + def setup_decorator(func): + @wraps(func) + def setup(self, *a, **kw): + if not hasattr(self, '__monkeystack__'): + self.__monkeystack__ = [] + patch = Patch([(module, name, that)]) + self.__monkeystack__.append(patch) + patch.apply() + return func(self, *a, **kw) + return setup + + def teardown_decorator(func): + @wraps(func) + def teardown(self, *a, **kw): + patch = self.__monkeystack__.pop() + patch.revert() + return func(self, *a, **kw) + return teardown + + def wrapper(cls): + cls.setUp = setup_decorator(cls.setUp) + cls.tearDown = teardown_decorator(cls.tearDown) + return cls + + return wrapper diff --git a/tests/monkeypatchTests.py b/tests/monkeypatchTests.py index b1b9359..2c52b4f 100644 --- a/tests/monkeypatchTests.py +++ b/tests/monkeypatchTests.py @@ -20,7 +20,7 @@ from testrunner import VdsmTestCase -import monkeypatch +from monkeypatch import Patch, MonkeyPatch, MonkeyClass class FakeModule: @@ -49,7 +49,7 @@ pass -class TestMonkeyPatchDecorator(VdsmTestCase): +class TestMonkeyPatch(VdsmTestCase): module = FakeModule() @@ -66,18 +66,46 @@ # This method patches module in one way - @monkeypatch.MonkeyPatch(module, 'a', patched) + @MonkeyPatch(module, 'a', patched) def testPatchOne(self): self.assertEqual(self.module.a, patched) self.assertNotEqual(self.module.b, patched) # This method patches module in another way - @monkeypatch.MonkeyPatch(module, 'a', patched) - @monkeypatch.MonkeyPatch(module, 'b', patched) + @MonkeyPatch(module, 'a', patched) + @MonkeyPatch(module, 'b', patched) def testPatchBoth(self): self.assertEqual(self.module.a, patched) self.assertEqual(self.module.b, patched) + + +module = FakeModule() + + +@MonkeyClass(module, 'a', patched) +class TestMonkeyClass(VdsmTestCase): + + def tearDown(self): + self.assertTrue(module.isClean()) + + def testPatched(self): + self.assertEqual(module.a, patched) + self.assertNotEqual(module.b, patched) + self.assertNotEqual(module.c, patched) + + +@MonkeyClass(module, 'a', patched) +@MonkeyClass(module, 'b', patched) +class TestMonkeyClassChain(VdsmTestCase): + + def tearDown(self): + self.assertTrue(module.isClean()) + + def testPatched(self): + self.assertEqual(module.a, patched) + self.assertEqual(module.b, patched) + self.assertNotEqual(module.c, patched) class TestMonkeyPatchFixture(VdsmTestCase): @@ -85,7 +113,7 @@ def __init__(self, *a, **kw): super(VdsmTestCase, self).__init__(*a, **kw) self.module = FakeModule() - self.patch = monkeypatch.Patch([ + self.patch = Patch([ (self.module, 'a', patched), (self.module, 'b', patched), ]) @@ -106,19 +134,19 @@ self.assertNotEqual(self.module.c, patched) -class TestMonkeyPatchAssertions(VdsmTestCase): +class TestMonkeyPatchFixtureAssertions(VdsmTestCase): def testAlreadyApplied(self): - patch = monkeypatch.Patch([(FakeModule(), 'a', patched)]) + patch = Patch([(FakeModule(), 'a', patched)]) patch.apply() self.assertRaises(AssertionError, patch.apply) def testNotApplied(self): - patch = monkeypatch.Patch([(FakeModule(), 'a', patched)]) + patch = Patch([(FakeModule(), 'a', patched)]) self.assertRaises(AssertionError, patch.revert) def testAlreadyReverted(self): - patch = monkeypatch.Patch([(FakeModule(), 'a', patched)]) + patch = Patch([(FakeModule(), 'a', patched)]) patch.apply() patch.revert() self.assertRaises(AssertionError, patch.revert) -- To view, visit http://gerrit.ovirt.org/20175 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ice429b01afaf00730ff59dcdf866ab5eeae6b926 Gerrit-PatchSet: 1 Gerrit-Project: vdsm Gerrit-Branch: master Gerrit-Owner: Nir Soffer <nsof...@redhat.com> _______________________________________________ vdsm-patches mailing list vdsm-patches@lists.fedorahosted.org https://lists.fedorahosted.org/mailman/listinfo/vdsm-patches