Skip to content

Instantly share code, notes, and snippets.

@keturn
Created August 10, 2011 20:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save keturn/1138086 to your computer and use it in GitHub Desktop.
Save keturn/1138086 to your computer and use it in GitHub Desktop.
asserting a function is a composite function
"""An example for discussion on "Fixing Untestable Code Sequences"
http://arlobelshee.com/post/mock-free-example-part-3-fixing-untestable-code-sequences
"""
from twisted.trial.unittest import TestCase
class ParserDoodle(object):
def parseCharacterIntoCards(self):
for powerElement in self.findAllPowers():
yield self.createPowerCard(powerElement)
def createPowerCard(self, powerElement):
localInfo = self.toPowerInfo(powerElement)
powerDetails = self.getOnlineInfoForPower(localInfo)
powerInfo = self.cleanTheResponse(powerDetails)
viewModel = self.createViewModel(powerInfo)
return viewModel
def findAllPowers(self):
return []
def toPowerInfo(self, powerElement):
return 'W'
def getOnlineInfoForPower(self, localInfo):
return 'X'
def cleanTheResponse(self, powerDetails):
return 'Y'
def createViewModel(self, powerInfo):
return 'Z'
class TestParserDoodle(TestCase):
def fakeComponent(self, expected, result):
def stub(x):
self.assertIdentical(expected, x)
return result
return stub
def assertIsComposite(self, func, components):
"""Assert the given function is a composite of the specified
functions.
:param func: f(x) -> x
:type func: callable
:param components: list of composite functions, specified as a tuple
of parent object and attribute name.
:type components: [object, str]
:return: None
"""
assert components
initialInput = object()
pipeInput = initialInput
for parent, componentName in components:
pipeOutput = object()
stub = self.fakeComponent(pipeInput, pipeOutput)
self.patch(parent, componentName, stub)
pipeInput = pipeOutput
result = func(initialInput)
#noinspection PyUnboundLocalVariable
self.assertIdentical(pipeOutput, result)
def test_createPowerCardIsComposition(self):
parser = ParserDoodle()
# this format is the easiest to pass to the patcher, but if you don't
# like the textual references to attributes because it makes IDEA's
# job harder, we could use object references and some more
# introspection.
components = [(parser, fn) for fn in [
'toPowerInfo',
'getOnlineInfoForPower',
'cleanTheResponse',
'createViewModel'
]]
self.assertIsComposite(parser.createPowerCard, components)
def test_createPowerCardIsImplementedLikeThis(self):
# This is what my tests of sequence operations often end up feeling
# like.
parser = ParserDoodle()
expected = """\
def createPowerCard(self, powerElement):
localInfo = self.toPowerInfo(powerElement)
powerDetails = self.getOnlineInfoForPower(localInfo)
powerInfo = self.cleanTheResponse(powerDetails)
viewModel = self.createViewModel(powerInfo)
return viewModel
"""
self.assertEqual(expected, getsource(parser.createPowerCard))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment