[Tutor] how to unittest cli input

Alex Kleider akleider at sonic.net
Sun Oct 11 18:29:56 CEST 2015


On 2015-10-10 18:10, Cameron Simpson wrote:

     On 10Oct2015 17:41, Alex Kleider <akleider at sonic.net> wrote:

         I'm tOn 2015-10-10 18:10, Cameron Simpson wrote:

     On 10Oct2015 17:41, 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.


     Aside: I'd say "the standard input" , not "the command line"; to me
     the latter connotes to command line arguments fro sys.argv.


Point well taken!   stdin it is.  Ben suggested I should have used the 
term "interactive" which certainly fits well.

     Anyway, ...

..................

     However, you'r eusing input(), which unconditionally uses stdin and
     stdout. In that circumstance I'd consider this:

      def collect_data(src=None, out=None):
          if src is None:
              src = sys.stdin
          if out is None:
              out = sys.stdout
          ostdin = sys.stdin
          sys.stdin = src
          ostdout = sys.stdout
          sys.stdout = out
          ret = {}
          ret['first'] = input("Enter your first name: ")
          ... etc ...
          sys.stdout = ostdout
          sys.stdin = ostdin

     Note that this is not thread safe because sys.stdin is a global, but
     it should work for testing.

     Anyway, perhap that gives you some way forward.


Yes indeed, and thank you for your input.
Here's where I'm going with your suggestion:

# collect.py

test_data = 'test_src.txt'

def data_collection_wrapper(collect, source=None):
     """
     """
     if source:
         ostdin = sys.stdin
         ostdout = sys.stdout
         src = open(source, 'r')
         sys.stdin = src
         out = open('/dev/null', 'w')  # Dump the prompts.
         sys.stdout = out

     ret = collect()

     if source:
         src.close()
         out.close()
         sys.stdin = ostdin
         sys.stdout = ostdout

     return ret


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

def main():
     print(collect_data())  # < check that user input works
     # then check that can test can be automated >
     print(data_collection_wrapper(collect_data,
                                     src=test_data))

if __name__ == "__main__":
     main()

Perhaps data_collection_wrapper could be made into a decorator (about
which I am still pretty naive.)

It'll take more studying on my part before I'll be able to implement 
Ben's suggestion.

Alex
ps I was tempted to change the "Subject:" to remove 'cli' and replace it 
with 'interactive' but remember many admonitions to not do that so have 
left it as is.



More information about the Tutor mailing list