473,796 Members | 2,826 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Acceptance test spike example

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.

First, I wrote an example test script I would hope to be able to execute...

===============
?recipeListCoun t:0
!new
?name:"New Recipe"
name:"PB&J"
?name:"PB&J"
!save
!close
?recipeListCoun t:1
!goToListItem 1
!openListItem
?name:"PB&J"
===============

In this script, ? means test a value, ! means execute an action, and a line
that starts with neither ? or ! is a value assignment.

Next, here's the Python code I wrote to try to run the script. This was just
proof of concept, so at this point, it just runs a single test script with the
script file name hard coded. Also, for simplicty, the skeleton of the
hypothetical application model object is, for now, in-line in the AT system
code.

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

def new(self):
pass

def save(self):
pass

def close(self):
pass

def goToListItem(se lf,itemNum):
pass

def openListItem(se lf):
pass
class ParsedStatement :
name = None
value = ""

def __init__(self,s tatementText,na meValuesDelim):
delimPos = string.find(sta tementText,name ValuesDelim)
if delimPos==-1:
self.name = statementText
else:
self.name = statementText[0:delimPos]
self.value = statementText[delimPos+1:]
class TestSession:
fileName=""
lines = None
model = RecipeOrgModel( )

def __init__(self,f ileName):
self.fileName = fileName

def run(self):
self.loadLines( self.fileName)

for line in self.lines:
if not self.processLin e(line): break

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

lines = map(string.stri p,lines)
self.lines = lines

def processLine(sel f,line):
print(line)

if line[0]=='?':
return(
self.TestValue( line[1:])
)
elif line[0]=='!':
self.DoAction(l ine[1:])
return 1
else:
self.AssignValu e(line)
return 1

def TestValue(self, statement):
parsed = ParsedStatement (statement,":")
valueExpr = "self.model ." + parsed.name
valueIs = eval(valueExpr)
valueExpected = eval(parsed.val ue)
hasExpectedVal = (valueExpected == valueIs)
if not hasExpectedVal:
print(" - Expected " + str(parsed.valu e) + ", but got " +
str(valueIs))
return(hasExpec tedVal)

def AssignValue(sel f,statement):
parsed = ParsedStatement (statement,":")
exec("self.mode l." + parsed.name + "=" + parsed.value)

def DoAction(self,s tatement):
parsed = ParsedStatement (statement," ")
methodCall = "self.model ." + parsed.name +"(" + parsed.value + ")"
exec(methodCall )
session = TestSession("te st1.txt")
session.run()
===============

Note how the powerful, context-aware exec() and eval() procedures really help
simplify the code.

Finally, here's the output I get when I run this with the example script above
saved in a file called test1.txt in the current directory.

===============
?recipeListCoun t:0
!new
?name:"New Recipe"
name:"PB&J"
?name:"PB&J"
!save
!close
?recipeListCoun t:1
- Expected 1, but got 0
===============

And this result is pretty much what we expect to see - cool.
Jul 19 '05 #1
6 1796
Steve Jorgensen 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.

First, I wrote an example test script I would hope to be able to execute...

===============
?recipeListCoun t:0
!new
?name:"New Recipe"
name:"PB&J"
?name:"PB&J"
!save
!close
?recipeListCoun t:1
!goToListItem 1
!openListItem
?name:"PB&J"
===============


Snipped.

Its best to aim the Acceptance Test at your Customers level of
expertise, not at the developers. As a Customer is the person best
placed to tell us What they want. Yes Our team people (Devs or testers)
can help write the actual tests, but the Customer should still be able
to read them. After all, the tests are Executable Requirements.

There's two flavors of Customer oriented styles I've come across.

The first uses a Domain Specific Language...eg using your values above..

---------------------------------
IsTotalNumberOf Recipes 0

ClickNewRecipeB utton
RecipeNameToUse "PB&J"
SaveNewRecipe
CloseDialog

IsTotalNumberOf Recipes 1

IsThereOneRecip eCalled "PB&J"
---------------------------------

All commands are the first full word. No need for special tokens to
decide what the command is supposed to do, as each Command is the name
of a class to use.

You can use reflection to dynamically create the Command instances or
the name can be used by a factory as an id.

The Commands themselves know what they are supposed to do, not the
Script parsing engine.

The second approach is using FIT/Fitnesse - google these for exact
description. They take information in Table form. This allows the
customer to use any software to create the test scripts, so long as it
can create tables: Word processors, Spread Sheets, etc.

Andrew
Jul 19 '05 #2

"Andrew McDonagh" <ne**@andrewcdo nagh.f2s.com> wrote in message
news:d9******** **@news.freedom 2surf.net...
Steve Jorgensen 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.

First, I wrote an example test script I would hope to be able to
execute...

===============
?recipeListCoun t:0
!new
?name:"New Recipe"
name:"PB&J"
?name:"PB&J"
!save
!close
?recipeListCoun t:1
!goToListItem 1
!openListItem
?name:"PB&J"
===============

Snipped.

Its best to aim the Acceptance Test at your Customers level of expertise,
not at the developers. As a Customer is the person best placed to tell us
What they want. Yes Our team people (Devs or testers) can help write the
actual tests, but the Customer should still be able to read them. After
all, the tests are Executable Requirements.

There's two flavors of Customer oriented styles I've come across.

The first uses a Domain Specific Language...eg using your values above..

---------------------------------
IsTotalNumberOf Recipes 0

ClickNewRecipeB utton
RecipeNameToUse "PB&J"
SaveNewRecipe
CloseDialog

IsTotalNumberOf Recipes 1

IsThereOneRecip eCalled "PB&J"
---------------------------------

All commands are the first full word. No need for special tokens to decide
what the command is supposed to do, as each Command is the name of a class
to use.

You can use reflection to dynamically create the Command instances or the
name can be used by a factory as an id.

The Commands themselves know what they are supposed to do, not the Script
parsing engine.

The second approach is using FIT/Fitnesse - google these for exact
description. They take information in Table form. This allows the customer
to use any software to create the test scripts, so long as it can create
tables: Word processors, Spread Sheets, etc.


The Python version of FIT (currently at 0.7a2) can be found in the
file section of either the FitNesse Yahoo group or the ExtremeProgramm ing
Yahoo group. One of these days I'm going to get it on PyPi.

It's full featured, works both in batch and with FitNesse, and
includes most of FitLibrary.

There's a book coming out on FIT (FIT for Developing Software)
by Rick Mugridge and Ward Cunningham. It was supposed to be out
a week ago Friday, but B&N says it was delayed.

John Roth
PyFit

Andrew


Jul 19 '05 #3

"Steve Jorgensen" <no****@nospam. nospam> wrote in message
news:mh******** *************** *********@4ax.c om...
Note how the powerful, context-aware exec() and eval() procedures really
help
simplify the code.
A stylistic note: I believe that most or all of your eval/exec uses could
be done with getattr and setattr instead, which are in the language for
precisely those situations in which the name of an attribute is in a
runtime string. To my mind, this would be simpler and better style.
valueExpr = "self.model ." + parsed.name
valueIs = eval(valueExpr)
I believe this is valueIs = getattr(self.mo del, parsed.name)
methodCall = "self.model ." + parsed.name +"(" + parsed.value + ")"
exec(methodCall )

I believe this is getattr(self.mo del, parsed.name)(pa rsed.value).

exec("self.mode l." + parsed.name + "=" + parsed.value)


I believe this is setattr(self.mo del, parsed.name, parsed.value).

and so on.

Terry J. Reedy

Jul 19 '05 #4
On Sun, 26 Jun 2005 22:42:40 -0400, "Terry Reedy" <tj*****@udel.e du> wrote:

"Steve Jorgensen" <no****@nospam. nospam> wrote in message
news:mh******* *************** **********@4ax. com...
Note how the powerful, context-aware exec() and eval() procedures really
help
simplify the code.


A stylistic note: I believe that most or all of your eval/exec uses could
be done with getattr and setattr instead, which are in the language for
precisely those situations in which the name of an attribute is in a
runtime string. To my mind, this would be simpler and better style.
valueExpr = "self.model ." + parsed.name
valueIs = eval(valueExpr)


I believe this is valueIs = getattr(self.mo del, parsed.name)
methodCall = "self.model ." + parsed.name +"(" + parsed.value + ")"
exec(methodCall )

I believe this is getattr(self.mo del, parsed.name)(pa rsed.value).

exec("self.mode l." + parsed.name + "=" + parsed.value)


I believe this is setattr(self.mo del, parsed.name, parsed.value).

and so on.


Thanks. I'm new to Python, so I'll take all the style advice I can get.

- Steve J.
Jul 19 '05 #5
On Sun, 26 Jun 2005 16:10:05 -0700, Steve Jorgensen
<no****@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.


Check out "Fit For Software Development". It should be published now.

-----
Robert C. Martin (Uncle Bob) | email: un******@object mentor.com
Object Mentor Inc. | blog: www.butunclebob.com
The Agile Transition Experts | web: www.objectmentor.com
800-338-6716
"The aim of science is not to open the door to infinite wisdom,
but to set a limit to infinite error."
-- Bertolt Brecht, Life of Galileo
Jul 19 '05 #6
On Sun, 26 Jun 2005 16:10:05 -0700, Steve Jorgensen <no****@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(se lf,itemNum):
pass

def openListItem(se lf):
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(act ionArgs, " ")
self.args = ""
if delimPos==-1:
self.item = actionArgs
else:
self.item = actionArgs[0:delimPos]
self.args = string.strip(ac tionArgs[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(act ionArgs, " to ")
self.args = ""
if delimPos==-1:
self.item = actionArgs
else:
self.value = eval( actionArgs[0:delimPos] )
self.item = string.strip(ac tionArgs[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(act ionArgs, " is ")
self.args = ""
if delimPos==-1:
self.item = actionArgs
else:
self.item = actionArgs[0:delimPos]
self.expectValu e = eval( string.strip(ac tionArgs[delimPos+len(" is
"):]) )

def tryAction(self, model):
valueIs = getattr(model, self.item)
if self.expectValu e == valueIs:
return True
else:
self.failMessag e = ( "Expected " + str(self.expect Value) +
" but got " + str(valueIs) )
return False
class ActionUnknown (Action):
actionArgs = ""

def __init__(self, actionArgs):
self.actionArgs = actionArgs

def tryAction(self, model):
self.failMessag e = "Test statement not understood: " + self.actionArgs
return False
def MakeTestAction( lineText):
delimPos = string.find(lin eText, " ")
commandArgs = ""
if delimPos==-1:
commandType = lineText
else:
commandType = lineText[0:delimPos]
commandArgs = string.strip(li neText[delimPos+1:])

if commandType == "Do":
return ActionDo(comman dArgs)
elif commandType == "Keyin":
return ActionKeyin(com mandArgs)
elif commandType == "Check":
return ActionCheck(com mandArgs)
elif commandType == "":
return NoAction(comman dArgs)
else:
return ActionUnknown(c ommandType + " " + commandArgs)
class TestSession:
fileName=""
lines = None
model = RecipeOrgModel( )

def __init__(self,f ileName):
self.fileName = fileName

def run(self):
self.loadLines( self.fileName)

for line in self.lines:
print(line)
action = MakeTestAction( line)
actionOk = action.tryActio n(self.model)
if not actionOk:
print(" !!! " + action.failMess age)
break

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

lines = map(string.stri p,lines)
self.lines = lines
session = TestSession("te st1.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
==========
Jul 19 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
2055
by: Remy Blank | last post by:
Ok, here we go. I added the possibility for tests using the unittest.py framework to be skipped. Basically, I added two methods to TestCase: TestCase.skip(msg): skips unconditionally TestCase.skipIf(expr, msg): skips if expr is true These can be called either in setUp() or in the test methods. I also added reporting of skipped tests to TestResult, _TextTestResult and
18
1871
by: alex | last post by:
Hi there, how can I check if a variable is a structure (i.e. a list)? For my special problem the variable is either a character string OR a list of character strings line So how can I test if a variable 'a' is either a single character string or a list? I tried: if a is list:
4
1542
by: Shabam | last post by:
I have a win2003 server running IIS with dotnet. Whenver I post a large amount of data to a dotnet application's form box, the cpu starts to spike up and down indefinitely. I stop IIS but the spike doesn't go away. Can this really happen even after IIS has been stopped? How do I find out what process is causing this? Looking at "processes" doesn't show anything. It appears the only way to stop this now is by rebooting the server.
38
3414
by: Christoph Zwerschke | last post by:
In August 2001, there was a thread about the "Art of Unit Testing": http://groups.google.com/group/comp.lang.python/browse_frm/thread/aa2bd17e7f995d05/71a29faf0a0485d5 Paul Moore asked the legitimate question why there is no hook for a "global" fixture code that is run only once for the whole TestCase, as opposed to the normal "setUp" and "tearDown" code that is run for every single test in the TestCase. A "global fixture" would be...
0
2314
by: Tim Haughton | last post by:
I've just released an article on using Test Driven Development with C# and Windows Forms. GUI's are often difficult to test, so I thought it might be of interest. The article along with the example source code can be downloaded here: http://www.blogitek.com/timhaughton/archives/files/User%20Interrogator%20And%20TDD.zip The article text is below. Not sure what it will do to the formatting when
2
1788
by: Isam | last post by:
Hello, Any help is greatly appreciated. I've recently upgraded my MSDE 2000 to SQL Server 2005 Express Edition on my Windows 2003 server SP1. I've noticted that running a single one table query against the new sql engine causes the sqlservr.exe process to consume 98% of CPU on the server. The spike usually lasts for a
2
1254
by: The Eternal Squire | last post by:
All, I've been doing some hacking of the Python engine, and I've been looking for where the comprehensive regression tests are kept so that I can determine where I've broken part of the engine. Thanks in advance,
1
3874
by: raj98 | last post by:
"It has been brought to our attention that your website mysite.com was causing 100% spike in CPU due to .NET 2.0 Error Reporting (dw20.exe) in our Shared Hosting environment. We will not be able to reinstate the website until the .NET 2.0 code has been repaired. Thank you for your understanding in this matter." This is what my host (godaddy) support has to say about the error. how do I resolve this issue? I only have access to the root...
18
3562
by: yashumrhsn | last post by:
can anyone help me to get userid and password from access database..then it compares the userid and password and opens a new from that shows the details from the database for that user..
0
10452
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10221
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10169
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10003
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
9050
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
6785
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5440
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
4115
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
3
2924
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.