[Tutor] unit testing raw_input()
Danny Yoo
dyoo at hkn.eecs.berkeley.edu
Wed Apr 19 03:39:29 CEST 2006
On Tue, 18 Apr 2006, Andre Roberge wrote:
> Suppose I had a function like the following:
>
> def y_n(prompt="Answer yes or no"):
> while True:
> answer = raw_input(prompt)
> if answer in ['y', 'Y', 'yes']:
> print "You said yes!"
> break
> elif answer in ['n', 'N', 'no']:
> print "You said no!"
> break
> else:
> print "%s is an invalid answer."%answer
>
> How could I go about to write an automated test for it?
Hi Andre,
One way to do this is to parameterize y_n() a little more to make it more
amendable to unit testing.
If we look at y_n(), we'd say that "raw_input()" is a free variable in
here --- its meaning comes from the outside environment as part of
builtins. We can change this by making it an explicit parameter:
########################################################
def y_n(prompt="Answer yes or no", raw_input=raw_input):
while True:
answer = raw_input(prompt)
if answer in ['y', 'Y', 'yes']:
print "You said yes!"
break
elif answer in ['n', 'N', 'no']:
print "You said no!"
break
else:
print "%s is an invalid answer."%answer
########################################################
Looks a little funny. *grin*
But now we can hardcode particular inputs by sending y_n() a mock
"raw_input" that returns precooked values.
###########################
def yes1_raw_input(prompt):
return "y"
def yes2_raw_input(prompt):
return "Y"
def yes3_raw_input(prompt):
return "yes"
def yes4_raw_input(prompt):
return "YES"
###########################
And then we can use these as part of our test case:
y_n(raw_input=yes1_raw_input)
We can also parameterize output in the same way. Right now, the function
is printing out the answer. Testing printed output is a little harder in
Python without fiddling around with stdout, but we can also make this also
a parameter of the function:
###################################################
def y_n(prompt="Answer yes or no",
raw_input=raw_input,
output=sys.stdout):
while True:
answer = raw_input(prompt)
if answer in ['y', 'Y', 'yes']:
print >>output, "You said yes!"
break
elif answer in ['n', 'N', 'no']:
print >>output, "You said no!"
break
else:
print >>output, "%s is an invalid answer."%answer
###################################################
Now we can inject our own output string that we can use to test what has
happened:
## pseudocode
import StringIO
test_output = StringIO.StringIO()
y_n(raw_input = yes4_raw_input,
output = test_output)
assertEquals("You said yes!", test_output.getvalue())
Does this make sense so far? y_n() in its original form might not be in
the right shape to make it easy to test, but we can turn it into a form
that is more easily testable.
Good luck!
More information about the Tutor
mailing list