[Tutor] how to unittest cli input
Danny Yoo
dyoo at hashcollision.org
Tue Oct 13 21:11:43 CEST 2015
On Sat, Oct 10, 2015 at 5:41 PM, Alex Kleider <akleider at sonic.net> wrote:
> """
> I'm trying to follow a test driven development paradigm (using
> unittest) but can't figure out how to test functions that collect
> info from the command line such as the following.
> """
> # collect.py
> def collect_data():
> ret = {}
> ret['first'] = input("Enter your first name: ")
> ret['last'] = input("Enter your last name: ")
> ret['phone'] = input("Your mobile phone #: ")
> return ret
Hi Alex,
If we look at collect_data in a funny way, we might see that it is a
"function" because it's parameterized by the behavior of the
interactive input() function. That means that we can make it a pure
function by explicitly treating "input" as a parameter.
#########################################
def collect_data(ask):
ret = {}
ret['first'] = ask("Enter your first name: ")
ret['last'] = ask("Enter your last name: ")
ret['phone'] = ask("Your mobile phone #: ")
return ret
#########################################
Making it an explicit parameter means that, when we call it, we can
feed it input() as the ask()er:
######################
def main():
print(collect_data(input))
######################
It also means that we can pass in an ask()er that is non-interactive,
which is good for unit tests. For example, here's one we can build up
quickly:
######################
def make_ask(f, l, p):
d = {'Enter your first name: ' : f,
'Enter your last name: ' : l,
'Your mobile phone #: ' : p}
return d.get
######################
What does this do? It gives us an ask that knows how to respond to
those questions. For example, at the interactive prompt:
##########################################
>>> ask = make_ask('jane', 'doe', '123456789')
>>> ask('Enter your first name: ')
'jane'
>>> ask('Enter your last name: ')
'doe'
##########################################
And now this is a tool we can use for unit testing the behavior of
collect_data. That is, we can say:
collect_data(make_ask('jane', 'doe', '12345'))
and know that we expect the dictionary value:
{'first': 'jane', ...}
The key is to look at interaction as an explicit parameter of your
function: once it's a parameter, then you can pass in custom
interactions that are controlled by your unit test.
More information about the Tutor
mailing list