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! _______________________________________________ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor