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

    On 10Oct2015 17:41, Alex Kleider <aklei...@sonic.net> wrote:

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

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

_______________________________________________
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor

Reply via email to