Unit tests with Python


/ Published in: Python
Save to your folder(s)

Test-first programming, in which you write the unit tests first with the unittest module and then work on the code until it passes all the tests, seems like a good substitute for writing interfaces or documentation first. The unit tests are like an API, describing the interface of the code being tested. And they lend themselves well to refactoring.

This is a first attempt at a unit test for the messager.py module posted earlier.


Copy this code and paste it in your HTML
  1. """Unit test for messager.py."""
  2.  
  3. from messager import messager, Receiver
  4. import unittest
  5.  
  6. class Logger(Receiver):
  7. """An object that maintains a log, in self.log, of the order in which its
  8. methods foo and bar are called and the arguments that are passed to them.
  9. Each item in the list is a 2-tuple: the method that was called, and a tuple
  10. of the arguments that were passed to it."""
  11.  
  12. def __init__(self):
  13.  
  14. # FIXME: log should be a class variable that all instances log to.
  15. self.log = []
  16.  
  17. def foo(self,*args):
  18.  
  19. self.log.append((self.foo,args))
  20.  
  21. def bar(self,*args):
  22.  
  23. self.log.append((self.bar,args))
  24.  
  25. class MessagerTest(unittest.TestCase):
  26.  
  27. def setUp(self):
  28.  
  29. self.logger = Logger()
  30.  
  31. def tearDown(self):
  32. pass
  33.  
  34. # Accepting and sending messages.
  35. def testMultipleAccept(self):
  36. """foo and bar are subscribed to message a, when a is sent both foo and
  37. bar should be called."""
  38.  
  39. self.logger.accept('a',self.logger.foo)
  40. self.logger.accept('a',self.logger.bar)
  41.  
  42. messager.send('a')
  43. # Two methods were called.
  44. self.assertEqual(len(self.logger.log),2)
  45. # foo was called once.
  46. count = self.logger.log.count((self.logger.foo,()))
  47. self.assertEqual(count,1)
  48. # bar was called once.
  49. count = self.logger.log.count((self.logger.bar,()))
  50. self.assertEqual(count,1)
  51.  
  52. def testAcceptOnce(self):
  53. """foo is subscribed to message b once only, bar is subscribed to it
  54. permanently. If b is sent twice, foo and bar should be called the first
  55. time, only bar should be called the second time."""
  56.  
  57. self.logger.acceptOnce('b',self.logger.foo)
  58. self.logger.accept('b',self.logger.bar)
  59.  
  60. messager.send('b')
  61. # foo should have been called once.
  62. count = self.logger.log.count((self.logger.foo,()))
  63. self.assertEqual(count,1)
  64. # bar should have been called once.
  65. count = self.logger.log.count((self.logger.bar,()))
  66. self.assertEqual(count,1)
  67. messager.send('b')
  68. # foo should still have been called only once.
  69. count = self.logger.log.count(( self.logger.foo,()))
  70. self.assertEqual(count,1)
  71. # bar should now have been called twice.
  72. count = self.logger.log.count((self.logger.bar,()))
  73. self.assertEqual(count,2)
  74.  
  75. # Ignoring messages.
  76. def testIgnore(self):
  77. """foo and bar are subscribed to c, after ignore(c,foo) only bar should
  78. be called when c is sent."""
  79.  
  80. self.logger.accept('c',self.logger.foo)
  81. self.logger.accept('c',self.logger.bar)
  82. self.logger.ignore('c',self.logger.foo)
  83. messager.send('c')
  84. # Only one method should have been called.
  85. self.assertEqual(len(self.logger.log),1)
  86. # bar should have been called once.
  87. count = self.logger.log.count((self.logger.bar,()))
  88. self.assertEqual(count,1)
  89.  
  90. def testIgnoreMessage(self):
  91. """foo and bar are subscribed to c, after ignore(c) neither foo nor bar
  92. should be called."""
  93.  
  94. self.logger.accept('c',self.logger.foo)
  95. self.logger.accept('c',self.logger.bar)
  96. self.logger.ignore('c')
  97. messager.send('c')
  98. # No methods should have been called.
  99. self.assertEqual(self.logger.log,[])
  100.  
  101. def testIgnoreAll(self):
  102. """After a Receiver object calls ignoreAll() no methods of this object
  103. should be called when any message is sent, but methods of other objects
  104. should continue to be called."""
  105.  
  106. self.logger.accept('d',self.logger.foo)
  107. self.logger.accept('e',self.logger.bar)
  108. second_logger = Logger()
  109. second_logger.accept('d',second_logger.foo)
  110. second_logger.accept('e',second_logger.bar)
  111.  
  112. self.logger.ignoreAll()
  113. messager.send('d')
  114. messager.send('e')
  115. # No methods of logger should have been called.
  116. self.assertEqual(self.logger.log,[])
  117. # Two methods should have been called on second_logger.
  118. self.assertEqual(len(second_logger.log),2)
  119. # foo should have been called once.
  120. count = second_logger.log.count((second_logger.foo,()))
  121. self.assertEqual(count,1)
  122. # bar should have been called once.
  123. count = second_logger.log.count((second_logger.bar,()))
  124. self.assertEqual(count,1)
  125.  
  126. # Clear.
  127. def testClear(self):
  128. """After clear has been called, sending a message should not result in
  129. any functions being called."""
  130.  
  131. messager.clear()
  132. messager.send('a')
  133. messager.send('b')
  134. messager.send('c')
  135. # No methods should have been called.
  136. self.assertEqual(self.logger.log,[])
  137.  
  138. # Sending with arguments.
  139. def testSendWithTwoArguments(self):
  140. """If accept is called with an argument and then send is called with an
  141. argument (and the same message name) the function subscribed via accept
  142. should be called with accept's argument followed by send's argument."""
  143.  
  144. self.logger.accept('f',self.logger.foo,'accepter arg')
  145. messager.send('f','sender arg')
  146. # One method should have been called.
  147. self.assertEqual(len(self.logger.log),1)
  148. # foo should have been called with the two arguments in the right order.
  149. count = self.logger.log.count((self.logger.foo,('accepter arg','sender arg')))
  150. self.assertEqual(count,1)
  151.  
  152. def testSendWithNoAccepterArgument(self):
  153. """If no argument is given to the accept method, but an argument is
  154. given to the send method, then the subscribed function(s) should be
  155. called with the send argument only."""
  156.  
  157. self.logger.accept('foo',self.logger.foo)
  158. messager.send('foo','sender arg')
  159. # One method should have been called.
  160. self.assertEqual(len(self.logger.log),1)
  161. # foo should have been called with the right argument.
  162. count = self.logger.log.count((self.logger.foo,('sender arg',)))
  163. self.assertEqual(count,1)
  164.  
  165. def testSendWithNoSenderArgument(self):
  166. """If no argument is given to the send method, but an argument is given
  167. to the accept method, then the subscribed function(s) should be called
  168. with the accept argument only."""
  169.  
  170. self.logger.accept('foo',self.logger.foo,'accepter arg')
  171. messager.send('foo')
  172. # One method should have been called.
  173. self.assertEqual(len(self.logger.log),1)
  174. # foo should have been called with the right argument.
  175. count = self.logger.log.count((self.logger.foo,('accepter arg',)))
  176. self.assertEqual(count,1)
  177.  
  178. if __name__ == '__main__':
  179. unittest.main()

Report this snippet


Comments

RSS Icon Subscribe to comments

You need to login to post a comment.