Acceptance test spike example

Steve Jorgensen nospam at nospam.nospam
Thu Jun 30 04:30:11 EDT 2005


On Sun, 26 Jun 2005 16:10:05 -0700, Steve Jorgensen <nospam at nospam.nospam>
wrote:

>I'm posting this message for 2 reasons.
>
>First, I'm still pretty new and shakey to the whole Acceptance Testing thing,
>and I'm hoping for some feedback on whether I'm on the right track.  Second,
>although all the Agile literature talks about the importance of doing
>Acceptance Testing, there's very little in any of the books or out on the Web
>that helps with how to do it.  If I am on the right track, this will be one
>more helpful item folks can find on a Google search.
>
>The code below is basically a spike I wrote in a few hours last night to prove
>to myself and my team that it would be feasible to quickly create a simple,
>useful Acceptance Testing harness for our learning project.
...

Here's an updated script and code to process the script.  I made the script
syntax more friendly.


New example script...

==========
Check  recipeListCount is 0

Do     new
Check  name is "New Recipe"

Keyin  "PB&J" to name
Ch eck  name is "PB&J"

Do     save
Do     close
Check  recipeListCount is 1

Do     goToListItem 1
Do     openListItem
Check  name is "PB&J"
==========


New Python code for test runner including skeleton of application model that
can be tested, but can't pass the tests...

==========
import string


class RecipeOrgModel:
    recipeListCount = 0
    name = "New Recipe"

    def new(self):
        pass

    def save(self):
        pass

    def close(self):
        pass

    def goToListItem(self,itemNum):
        pass

    def openListItem(self):
        pass


class Action:
    failMessage = ""
    
    def __init__(self, actionArgs):
        pass
    
    def tryAction(self, model):
        return True


class NoAction (Action):
    pass

class ActionDo (Action):
    item  = ""
    args = ""
    
    def __init__(self, actionArgs):
        delimPos = string.find(actionArgs, " ")
        self.args = ""
        if delimPos==-1:
            self.item = actionArgs
        else:
            self.item = actionArgs[0:delimPos]
            self.args = string.strip(actionArgs[delimPos+1:])
    
    def tryAction(self, model):
        methodCall = "model." + self.item +"(" + self.args + ")"
        exec(methodCall)
        return True
    

class ActionKeyin (Action):
    item  = ""
    value = ""
    
    def __init__(self, actionArgs):
        delimPos = string.find(actionArgs, " to ")
        self.args = ""
        if delimPos==-1:
            self.item = actionArgs
        else:
            self.value = eval( actionArgs[0:delimPos] )
            self.item = string.strip(actionArgs[delimPos+len(" to "):])
    
    def tryAction(self, model):
        setattr(model, self.item, self.value)
        return True


class ActionCheck (Action):
    item  = ""
    expectValue = ""
    
    def __init__(self, actionArgs):
        delimPos = string.find(actionArgs, " is ")
        self.args = ""
        if delimPos==-1:
            self.item = actionArgs
        else:
            self.item = actionArgs[0:delimPos]
            self.expectValue = eval( string.strip(actionArgs[delimPos+len(" is
"):]) )
    
    def tryAction(self, model):
        valueIs = getattr(model, self.item)
        if self.expectValue == valueIs:
            return True
        else:
            self.failMessage = ( "Expected " + str(self.expectValue) +
                                 " but got " + str(valueIs) )
            return False


class ActionUnknown (Action):
    actionArgs = ""
    
    def __init__(self, actionArgs):
        self.actionArgs = actionArgs
    
    def tryAction(self, model):
        self.failMessage = "Test statement not understood: " + self.actionArgs
        return False


def MakeTestAction(lineText):
    delimPos = string.find(lineText, " ")
    commandArgs = ""
    if delimPos==-1:
        commandType = lineText
    else:
        commandType = lineText[0:delimPos]
        commandArgs = string.strip(lineText[delimPos+1:])

    if commandType == "Do":
        return ActionDo(commandArgs)
    elif commandType == "Keyin":
        return ActionKeyin(commandArgs)
    elif commandType == "Check":
        return ActionCheck(commandArgs)
    elif commandType == "":
        return NoAction(commandArgs)
    else:
        return ActionUnknown(commandType + " " + commandArgs)


class TestSession:
    fileName=""
    lines = None
    model = RecipeOrgModel()
    
    def __init__(self,fileName):
        self.fileName = fileName
    
    def run(self):
        self.loadLines(self.fileName)

        for line in self.lines:
            print(line)
            action = MakeTestAction(line)
            actionOk = action.tryAction(self.model)
            if not actionOk:
                print(" !!! " + action.failMessage)
                break

    def loadLines(self, fileName):
        file = open(fileName)
        lines = file.readlines()
        file.close
        
        lines = map(string.strip,lines)
        self.lines = lines

        
session = TestSession("test1.txt")
session.run()
==========


Ouptut of test runner using example script...

==========
Check  recipeListCount is 0

Do     new
Check  name is "New Recipe"

Keyin  "PB&J" to name
Check  name is "PB&J"

Do     save
Do     close
Check  recipeListCount is 1
 !!! Expected 1 but got 0
==========



More information about the Python-list mailing list