Change in vdsm[master]: tests: Add monkey patching class decorator

nsoffer at redhat.com nsoffer at redhat.com
Mon Oct 14 22:16:44 UTC 2013


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 <nsoffer at 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()
+
+
+ at 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)
+
+
+ at MonkeyClass(module, 'a', patched)
+ at 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 <nsoffer at redhat.com>


More information about the vdsm-patches mailing list