#1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2014
    Posts
    22
    Rep Power
    0

    Trying to make a test for a script where there is a CLI


    Hi all,

    I made this dummy script and I'm trying to use doctest in order to automate several things for testing. One particular problem that I'm having is that when I use raw_input in order to get some input from the user at the CLI, doctest does not fill this information in by default.

    The script (unnecessary_math.py):
    Code:
    #!/usr/bin/env python
    
    """
    Module showing how doctests can be included with source code
    Each '>>>' line is run as if in a python shell, and counts as a test.
    The next line, if not '>>>' is the expected output of the previous line.
    If anything doesn't match exactly (including trailing spaces), the test fails.
    """
     
    def multiply(a, b):
      """
      >>> multiply(4, 3)
      12
      >>> multiply('a', 3)
      'aaa'
      """
    
      return a * b
    
    def main():
      confirm_char = raw_input(" New input: ")
      print ""
      print "This is what was inputted: ", confirm_char
    
    if __name__ == "__main__":
      main()
    The doctest test (test_unnecessary_math.txt):
    Code:
    This is a doctest based regression suite for unnecessary_math.py
    Each '>>' line is run as if in a python shell, and counts as a test.
    The next line, if not '>>' is the expected output of the previous line.
    If anything doesn't match exactly (including trailing spaces), the test fails.
     
    >>> from unnecessary_math import multiply
    >>> multiply(3, 4)
    12
    >>> multiply('a', 3)
    'aaa'
    >>> import unnecessary_math
    >>> unnecessary_math.main()
     New input: asdfadsf
    
    This is what was inputted:  asdfadsf
    And this is what happens when I try to run my test on the dummy script:
    Code:
    > python -m doctest -v test_unnecessary_math.txt
    Trying:
        from unnecessary_math import multiply
    Expecting nothing
    ok
    Trying:
        multiply(3, 4)
    Expecting:
        12
    ok
    Trying:
        multiply('a', 3)
    Expecting:
        'aaa'
    ok
    Trying:
        import unnecessary_math
    Expecting nothing
    ok
    Trying:
        unnecessary_math.main()
    Expecting:
         New input: asdfadsf
    
    **********************************************************************
    File "test_unnecessary_math.txt", line 12, in test_unnecessary_math.txt
    Failed example:
        unnecessary_math.main()
    Expected:
         New input: asdfadsf
    Got:
         New input: 
        This is what was inputted:  
    **********************************************************************
    1 items had failures:
       1 of   5 in test_unnecessary_math.txt
    5 tests in 1 items.
    4 passed and 1 failed.
    ***Test Failed*** 1 failures.
    My question is this. How can automate certain inputs at the command line into my script? Is this something that I can do in doctest or do I need an another approach?

    Thanks in advance.
  2. #2
  3. Contributing User
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Aug 2011
    Posts
    5,859
    Rep Power
    509
    How do you invoke doctest? Here, and as you've shown, importing as a module bypasses raw_input
    Code:
    $ python -m doctest -v unnecessary_math.py 
    Trying:
        multiply(4, 3)
    Expecting:
        12
    ok
    Trying:
        multiply('a', 3)
    Expecting:
        'aaa'
    ok
    2 items had no tests:
        unnecessary_math
        unnecessary_math.main
    1 items passed all tests:
       2 tests in unnecessary_math.multiply
    2 tests in 3 items.
    2 passed and 0 failed.
    Test passed.
    • Maintain a shell script that works with the program.
      Code:
      '''
          doctest invoked with shell command:   echo hello world | python -m doctest p.py
          >>> f()
          received hello world
      '''
      
      def f():
          a = raw_input()
          print 'received', a
    • python version 1 solution: replace sys.stdin for the duration of the test with file like buffer
      Code:
      '''
          doctest invoked with shell command:   python -m doctest p.py
      
          >>> import sys
          >>> import io
          >>> test_input = io.StringIO(u'hello world')
          >>> (sys.stdin, stdin,) = (test_input, sys.stdin,) # save and replace sys.stdin
          >>> f()
          received hello world
          >>> sys.stdin = stdin  # restore sys.stdin
      '''
      
      def f():
          a = raw_input()
          print 'received', a
    • I prefer using file objects whereas raw_input restricts the input to sys.stdin
      Code:
      #! /usr/bin/python3
      
      '''
          doctest invoked with shell command:   python3 -m doctest p.py
      
          >>> import io
          >>> test_input = io.StringIO('hello world')
          >>> f(test_input)
          received hello world
      '''
      
      import sys
      
      def raw(inf = sys.stdin):
          a = inf.readline()
          if a[-1] == '\n':
              a = a[:-1]
          return a
      
      def f(inf):
          a = raw(inf)
          print('received', a)

    Comments on this post

    • elephantcoder agrees
    [code]Code tags[/code] are essential for python code and Makefiles!
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2014
    Posts
    22
    Rep Power
    0
    I invoke it like so:
    Code:
    python -m doctest -v test_unnecessary_math.txt
  6. #4
  7. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2014
    Posts
    22
    Rep Power
    0
    Thanks, this helped. I added the test_input = io.StringIO(u'hello world') and that got me the info from raw_input.
  8. #5
  9. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2014
    Posts
    22
    Rep Power
    0
    @b49P23Tlvg, what if I were to use the unittest module? Basically, I'm writing a bunch of unit tests and I have a point in my function where I need the user to enter a string. How can I simulate that?

    Is there something similar that can be done for unittest that you posted on doctest?
  10. #6
  11. Contributing User
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Aug 2011
    Posts
    5,859
    Rep Power
    509
    ugh. Our team used unittest and found that we had to write extra code to make it useful. good luck. Maybe I'll try harder tomorrow. I gave up with unittest and find doctest easier and sufficient.
    [code]Code tags[/code] are essential for python code and Makefiles!
  12. #7
  13. Contributing User
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Aug 2011
    Posts
    5,859
    Rep Power
    509
    in post #2, the 4th [code][/code]I showed how to use the io.StringIO class to simulate user input. Now, if you'll explain how to simulate mouse input we'll be good. I do know how to do it in chrome.
    [code]Code tags[/code] are essential for python code and Makefiles!
  14. #8
  15. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2014
    Posts
    22
    Rep Power
    0
    Originally Posted by b49P23TIvg
    ugh. Our team used unittest and found that we had to write extra code to make it useful. good luck. Maybe I'll try harder tomorrow. I gave up with unittest and find doctest easier and sufficient.
    Do you use just doctest or any other test framework?
  16. #9
  17. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2014
    Posts
    22
    Rep Power
    0
    Originally Posted by b49P23TIvg
    in post #2, the 4th [code][/code]I showed how to use the io.StringIO class to simulate user input. Now, if you'll explain how to simulate mouse input we'll be good. I do know how to do it in chrome.
    What Python test framework does simulate mouse input? Or is it none of them?
  18. #10
  19. Contributing User
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Aug 2011
    Posts
    5,859
    Rep Power
    509
    GUIs let you simulate events. For instance tkinter has an event_generate method. I use doctest and don't use another python test 'framework'.
    [code]Code tags[/code] are essential for python code and Makefiles!

IMN logo majestic logo threadwatch logo seochat tools logo