[Tutor] TDD: How to test input()?

Steven D'Aprano steve at pearwood.info
Sat Oct 8 02:18:54 EDT 2016


On Fri, Oct 07, 2016 at 08:26:28PM -0500, boB Stepp wrote:
> I think I have this figured out, but I want to be certain I am doing
> it both correctly and in the preferred way.  I have a need for a
> get_input() function and have written my first test for this function
> as follows:

Testing code that depends on user input is always tricky. There are a 
few ways to deal with it:

(1) Denial. Just don't test that part of your code at all. That's not 
ideal, but it may be "good enough" if any error in that code would be 
obvious enough.

(2) Perform ad hoc non-automated tests that require user intavention. 
That's a bit better but still not great.

(3) You can monkey-patch the input() function in your test:

import mymodule  # module being tested

class MyTests(unittest.TestCase):
    def test_get_input(self):

       def myinput(prompt):
           return "5"

        mymodule.input = myinput
        try:
            result = mymodule.get_input("What number do you want?")
            self.assertEqual(result, 5)
        finally:
            del mymodule.input


That's often a good solution for simple testing.

(4) Python 3 unittest library now includes support for mocking:

https://docs.python.org/3/library/unittest.mock.html


which lets you replace parts of your code with fake code ("mocks") which 
are more easily tested, similar to the monkey-patch example in (3) 
above. For an example, look at the test suite for the "code" module:

https://docs.python.org/3/library/code.html

https://hg.python.org/cpython/file/3.5/Lib/test/test_code_module.py


(5) Or you could manually monkey-patch sys.stdin as you do.


I haven't studied your code in detail to comment on it yet. Time 
permitting, I shall do so later.



-- 
Steve


More information about the Tutor mailing list