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

2016-10-08 Thread Alan Gauld via Tutor
On 08/10/16 07:18, Steven D'Aprano wrote:

> Testing code that depends on user input is always tricky. There are a 
> few ways to deal with it:
> 
> (5) Or you could manually monkey-patch sys.stdin as you do.

A variation on this that I have used is to read the input
from stdin as usual but redirect stdin when you run the
code:

python test_input.py < testdata.txt

That way I can use multiple sets of test data and run
the tests using the different data sets. The test suite
is then exercised by a simple shell script that runs
against each test file in turn.

I find that easier and more flexible than using a
StringIO buffer. You can catch EOF errors in your
test rig or write the tests to read a finite set
of data and create the data to match.

-- 
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos


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


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

2016-10-08 Thread Steven D'Aprano
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
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


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

2016-10-07 Thread boB Stepp
Oops!

On Fri, Oct 7, 2016 at 8:26 PM, 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:
>
> class TestGetInput(unittest.TestCase):
> '''Tests for the function get_input().'''
>
> def setUp(self):
> '''Establish conditions for running these tests.'''
>
> # Redirect sys.stdin in order to test input functions.
> self.old_stdin = sys.stdin
> sys.stdin = StringIO('5')
>
> def test_get_input(self):
> '''Test that get_input() returns the expected result.'''
>
> expected = 5
> draw2x2grid.get_input()
> self.assertEqual(sys.stdin.getvalue(), expected)

My brain was scrambled.  The test_get_input(self) should instead be:

def test_get_input(self):
'''Test that get_input() returns the expected result.'''

expected = 5
self.assertEqual(draw2x2grid.get_input(), expected)

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