Reputation: 1592
I am looking to find a way to pass random values to a python code which takes multiple user inputs from the user command line from following python command. I think it could help me in testing.
num = input("Some prompt")
Is there any method/way to automatically (programatically) pass values to these python input() functions without waiting for user input on console ?
Also, my code takes multiple inputs from user based on a user input which specifies how many user inputs to fetch.
My code:
def delicious_prize(n):
##N no of boxes
##K product number of chocklates in N boxes
##T total no of test cases
print("n = ", n)
if not isinstance(n, int):
print("Not integer type. Only int accepted. Aborting")
return False
elif not n <= 1000:
print("Inpute n: %s is not in range. Should be less than or equal to 1000"%(n))
exit
elif n < 0:
print("No of boxes cannot be negative. Taking positve magnitude as %s"%(abs(n)))
n = abs(n)
elif n == 0:
print("No chocklate boxes offered !")
exit
num_list = []
for i in range(n):
num = input("Enter no of chocklates in %sth box : "%(i))
num_list.append(int(num))
num_tuple = tuple(num_list)
print(num_tuple)
return tuple_count(num_tuple)
if __name__=='__main__':
print(delicious_prize(2))
print(delicious_prize(0))
print(delicious_prize(-3))
print(delicious_prize('wqete'))
Upvotes: 0
Views: 440
Reputation: 91
I would rather replace sys.stdin
when you are doing the testing:
import StringIO
import sys
sys.stdin = StringIO.StringIO("1000\n")
num = input("some number: ")
print("\nread %d from input" % num)
Step through the example above at https://dbgr.cc/4u#autoPlay=true
Upvotes: 1
Reputation: 10238
There is a very obvious way to replace the built-in input function. Just insert two lines at the beginning of the part you dedicated to testing:
if __name__=='__main__':
import random
input = lambda s: random.randint(1, 12)
print(delicious_prize(2))
print(delicious_prize(0))
print(delicious_prize(-3))
print(delicious_prize('wqete'))
You asked for randomness that's why I used it - I'd probably start with a constant input:
input = lambda s: 6
Upvotes: 1
Reputation: 55469
Another way to feed data to a program that's expecting console input is to use input redirection
You just put the data you want to input into a plain text file (eg data.txt), with one input string per line, and then you can do:
python myprog.py < data.txt
There are variations on this theme, eg feeding the output of one program into the input of another, as the Wikipedia article explains.
The main advantage of this method is that you don't have to modify myprog.py
in any way, but the disadvantage is that the stuff printed by your input prompts will look a little bit weird because the data read from the file will not be echoed to the console. Also, this technique isn't as flexible as the techniques discussed by Wolf and Martijn Pieters. But it can be very handy.
Upvotes: 1
Reputation: 1121962
You can replace the input()
function with your own. A dedicated package for doing this during testing is part of the Python standard library: unittest.mock
.
In your test you'd mock input()
and have it return specific values, or entirely random values:
if __name__=='__main__':
from unittest import mock
with mock.patch('__main__.input', create=True) as mocked_input:
mocked_input.side_effect = ['first input', 'second input', 'third input']
delicious_prize(3)
In the above code, a new input
object is inserted into your module, masking the built-in input()
function. When it is called by code in delicious_prize
, each time another value from the side_effect
attribute list is returned.
In this specific test, the strings are not valid numbers; your real tests would use values that can be converted to integers.
When testing, always pass in predictable values; you want your unit tests to be solid and repeatable, not fail just some of the time.
Upvotes: 3
Reputation: 10238
As quamrana suggested in a comment, you can pass your own input function as parameter.
import random
def test(x, input=input): # input function, defaults to the built-in one
v=input("Your input: ")
print v==x
results = (3, 4)
def ran(s):
i = random.choice(results)
print s+str(i)
return i
test(3, ran)
test(4, ran)
test(4)
Output (depending on random
and your input) may look like this:
Your input: 4
False
Your input: 3
False
Your input: 4
True
BTW: Testability is only one reason for isolating function logic from specific ways of input and output.
Upvotes: 0