Guest User

Untitled

a guest
Jun 14th, 2013
155
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. from twisted.trial.unittest import TestCase
  2. from twisted.protocols.amp import (
  3.     Command, Integer, CommandLocator, BoxDispatcher, COMMAND, ASK, ANSWER)
  4.  
  5. ################### Application code ###################
  6.  
  7.  
  8. class Sum(Command):
  9.  
  10.     arguments = [("a", Integer()), ("b", Integer())]
  11.     response = [("result", Integer())]
  12.  
  13.  
  14. class Math(CommandLocator):
  15.  
  16.     @Sum.responder
  17.     def sum(self, a, b):
  18.         return {"result": a + b}
  19.  
  20.  
  21. class MathClient(object):
  22.     """This is an example of application client code using C{callRemote}.
  23.  
  24.    It just provides a convenient abstraction around the application-defined
  25.    AMP commands.
  26.    """
  27.  
  28.     def __init__(self, protocol):
  29.         """
  30.        @param protocol: An C{AMP} instance connected to a remote L{Math}
  31.            command locator.
  32.        """
  33.         self._protocol = protocol
  34.  
  35.     def sum(self, a, b):
  36.         deferred = self._protocol.callRemote(Sum, a=a, b=b)
  37.         return deferred.addCallback(lambda response: response["result"])
  38.  
  39.  
  40. ################### Application tests ###################
  41.  
  42.  
  43. class FakeBoxSender(object):
  44.  
  45.     def __init__(self):
  46.         self.sent = []
  47.  
  48.     def sendBox(self, box):
  49.         self.sent.append(box)
  50.  
  51.  
  52. class MathTest(TestCase):
  53.  
  54.     def setUp(self):
  55.         super(MathTest, self).setUp()
  56.         locator = Math()
  57.         self.dispatcher = BoxDispatcher(locator)
  58.         self.sender = FakeBoxSender()
  59.         self.dispatcher.startReceivingBoxes(self.sender)
  60.  
  61.     def test_sum_request(self):
  62.         """
  63.        This is mainly a wiring test, asserting that L{Math.sum} is decorated
  64.        with @Sum.responder.
  65.  
  66.        Incidentally it also exercises L{Sum.arguments} and implies that the
  67.        'a' and 'b' arguments are deserialized to C{int}s.
  68.  
  69.        One would ideally also test the L{Method.sum} on its own directly, by
  70.        instantiating the L{Math} class, and really exercising all its actual
  71.        logic.
  72.        """
  73.         box = {COMMAND: "Sum", ASK: "1", "a": "3", "b": "2"}
  74.         self.dispatcher.ampBoxReceived(box)
  75.         self.assertEqual(self.sender.sent, [{ANSWER: "1", "result": "5"}])
  76.  
  77.     def test_sum_response(self):
  78.         """
  79.        Maybe there should be a test for exercising L{Sum.response} too?
  80.  
  81.        It would directly or indirectly, make sure that the 'result' field is
  82.        deserialized to C{int}.
  83.        """
  84.  
  85.  
  86. class FakeBoxDispatcher(object):
  87.  
  88.     def __init__(self, locator):
  89.         self.locator = locator
  90.  
  91.     def callRemote(self, commandType, *a, **kw):
  92.         """
  93.        Faking C{callRemote} this way is slightly unfortunate because it
  94.        duplicates the real AMP logic a bit, but it might acceptable.
  95.        """
  96.         responder = self.locator.locateResponder(commandType.commandName)
  97.         deferred = responder(kw)
  98.         return deferred.addCallback(commandType.parseResponse, self)
  99.  
  100.  
  101. class MathClientTest(TestCase):
  102.  
  103.     def setUp(self):
  104.         super(MathClientTest, self).setUp()
  105.         locator = Math()
  106.         dispatcher = FakeBoxDispatcher(locator)
  107.         self.client = MathClient(dispatcher)
  108.  
  109.     def test_sum(self):
  110.         """
  111.        This tests L{MathClient}, and it does so by running a real L{Math}
  112.        command locator, except that there is no network/transport involved.
  113.  
  114.        Other layers of the application code using L{MathClient} could as well
  115.        have their tests setup using a real L{MatchClient} instantiated with
  116.        a L{FakeBoxDispatcher} as well, as opposed to creating fake versions
  117.        of L{MathClient}.
  118.  
  119.        This would of course make such higher-layer tests more "integration"
  120.        and less "unit", but in practice it might be more convenient and
  121.        give more confidence that mocking out L{MathClient} (drifting to
  122.        state-based vs. behavior-based testing here, sorry).
  123.        """
  124.         deferred = self.client.sum(3, 2)
  125.         self.assertEqual(5, self.successResultOf(deferred))
Advertisement
Add Comment
Please, Sign In to add comment