Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

test_monkey.py 6.1KB

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. # Copyright (c) Twisted Matrix Laboratories.
  2. # See LICENSE for details.
  3. """
  4. Tests for L{twisted.python.monkey}.
  5. """
  6. from twisted.python.monkey import MonkeyPatcher
  7. from twisted.trial import unittest
  8. class TestObj:
  9. def __init__(self):
  10. self.foo = "foo value"
  11. self.bar = "bar value"
  12. self.baz = "baz value"
  13. class MonkeyPatcherTests(unittest.SynchronousTestCase):
  14. """
  15. Tests for L{MonkeyPatcher} monkey-patching class.
  16. """
  17. def setUp(self):
  18. self.testObject = TestObj()
  19. self.originalObject = TestObj()
  20. self.monkeyPatcher = MonkeyPatcher()
  21. def test_empty(self):
  22. """
  23. A monkey patcher without patches shouldn't change a thing.
  24. """
  25. self.monkeyPatcher.patch()
  26. # We can't assert that all state is unchanged, but at least we can
  27. # check our test object.
  28. self.assertEqual(self.originalObject.foo, self.testObject.foo)
  29. self.assertEqual(self.originalObject.bar, self.testObject.bar)
  30. self.assertEqual(self.originalObject.baz, self.testObject.baz)
  31. def test_constructWithPatches(self):
  32. """
  33. Constructing a L{MonkeyPatcher} with patches should add all of the
  34. given patches to the patch list.
  35. """
  36. patcher = MonkeyPatcher(
  37. (self.testObject, "foo", "haha"), (self.testObject, "bar", "hehe")
  38. )
  39. patcher.patch()
  40. self.assertEqual("haha", self.testObject.foo)
  41. self.assertEqual("hehe", self.testObject.bar)
  42. self.assertEqual(self.originalObject.baz, self.testObject.baz)
  43. def test_patchExisting(self):
  44. """
  45. Patching an attribute that exists sets it to the value defined in the
  46. patch.
  47. """
  48. self.monkeyPatcher.addPatch(self.testObject, "foo", "haha")
  49. self.monkeyPatcher.patch()
  50. self.assertEqual(self.testObject.foo, "haha")
  51. def test_patchNonExisting(self):
  52. """
  53. Patching a non-existing attribute fails with an C{AttributeError}.
  54. """
  55. self.monkeyPatcher.addPatch(self.testObject, "nowhere", "blow up please")
  56. self.assertRaises(AttributeError, self.monkeyPatcher.patch)
  57. def test_patchAlreadyPatched(self):
  58. """
  59. Adding a patch for an object and attribute that already have a patch
  60. overrides the existing patch.
  61. """
  62. self.monkeyPatcher.addPatch(self.testObject, "foo", "blah")
  63. self.monkeyPatcher.addPatch(self.testObject, "foo", "BLAH")
  64. self.monkeyPatcher.patch()
  65. self.assertEqual(self.testObject.foo, "BLAH")
  66. self.monkeyPatcher.restore()
  67. self.assertEqual(self.testObject.foo, self.originalObject.foo)
  68. def test_restoreTwiceIsANoOp(self):
  69. """
  70. Restoring an already-restored monkey patch is a no-op.
  71. """
  72. self.monkeyPatcher.addPatch(self.testObject, "foo", "blah")
  73. self.monkeyPatcher.patch()
  74. self.monkeyPatcher.restore()
  75. self.assertEqual(self.testObject.foo, self.originalObject.foo)
  76. self.monkeyPatcher.restore()
  77. self.assertEqual(self.testObject.foo, self.originalObject.foo)
  78. def test_runWithPatchesDecoration(self):
  79. """
  80. runWithPatches should run the given callable, passing in all arguments
  81. and keyword arguments, and return the return value of the callable.
  82. """
  83. log = []
  84. def f(a, b, c=None):
  85. log.append((a, b, c))
  86. return "foo"
  87. result = self.monkeyPatcher.runWithPatches(f, 1, 2, c=10)
  88. self.assertEqual("foo", result)
  89. self.assertEqual([(1, 2, 10)], log)
  90. def test_repeatedRunWithPatches(self):
  91. """
  92. We should be able to call the same function with runWithPatches more
  93. than once. All patches should apply for each call.
  94. """
  95. def f():
  96. return (self.testObject.foo, self.testObject.bar, self.testObject.baz)
  97. self.monkeyPatcher.addPatch(self.testObject, "foo", "haha")
  98. result = self.monkeyPatcher.runWithPatches(f)
  99. self.assertEqual(
  100. ("haha", self.originalObject.bar, self.originalObject.baz), result
  101. )
  102. result = self.monkeyPatcher.runWithPatches(f)
  103. self.assertEqual(
  104. ("haha", self.originalObject.bar, self.originalObject.baz), result
  105. )
  106. def test_runWithPatchesRestores(self):
  107. """
  108. C{runWithPatches} should restore the original values after the function
  109. has executed.
  110. """
  111. self.monkeyPatcher.addPatch(self.testObject, "foo", "haha")
  112. self.assertEqual(self.originalObject.foo, self.testObject.foo)
  113. self.monkeyPatcher.runWithPatches(lambda: None)
  114. self.assertEqual(self.originalObject.foo, self.testObject.foo)
  115. def test_runWithPatchesRestoresOnException(self):
  116. """
  117. Test runWithPatches restores the original values even when the function
  118. raises an exception.
  119. """
  120. def _():
  121. self.assertEqual(self.testObject.foo, "haha")
  122. self.assertEqual(self.testObject.bar, "blahblah")
  123. raise RuntimeError("Something went wrong!")
  124. self.monkeyPatcher.addPatch(self.testObject, "foo", "haha")
  125. self.monkeyPatcher.addPatch(self.testObject, "bar", "blahblah")
  126. self.assertRaises(RuntimeError, self.monkeyPatcher.runWithPatches, _)
  127. self.assertEqual(self.testObject.foo, self.originalObject.foo)
  128. self.assertEqual(self.testObject.bar, self.originalObject.bar)
  129. def test_contextManager(self):
  130. """
  131. L{MonkeyPatcher} is a context manager that applies its patches on
  132. entry and restore original values on exit.
  133. """
  134. self.monkeyPatcher.addPatch(self.testObject, "foo", "patched value")
  135. with self.monkeyPatcher:
  136. self.assertEqual(self.testObject.foo, "patched value")
  137. self.assertEqual(self.testObject.foo, self.originalObject.foo)
  138. def test_contextManagerPropagatesExceptions(self):
  139. """
  140. Exceptions propagate through the L{MonkeyPatcher} context-manager
  141. exit method.
  142. """
  143. with self.assertRaises(RuntimeError):
  144. with self.monkeyPatcher:
  145. raise RuntimeError("something")