I have a use case where a function seeks user confirmation to proceed. This is basically:
def abc()
response = click.confirm("Do you want to continue?")
Based on this response, it either aborts or proceeds.
The problem is to test this function abc.
#click.option('--yes', prompt=True)
def test_abc():
with mock.patch.object(click.confirm, input="n"):
click.echo("Aborted")
Old question but I had the same issue, I decided to mock the click.confirm which allowed me to simulate someone selecting [y/N]
lets say your abc() looked like this:
def abc():
if click.confirm("do you want to continue?", abort=True):
return "Confirmed"
return "Aborted"
and then your tests mock the click.confirm to y/n
#mock.patch("click.confirm")
def test_abc_aborted(mock_click):
mock_click.return_value = False
assert abc() == "Aborted"
#mock.patch("click.confirm")
def test_abc_confirmed(mock_click):
mock_click.return_value = "y"
assert abc() == "Confirmed"
Related
I want to test a file called ninja.py wrote in Python3.6.
# File ninja.py
def what_to_do_result(result):
# Send a mail, write something in a file, play a song or whatever
def my_function(a, b):
# Step 1
result = a + b
# Step 2
if result == 3:
what_to_do_result(result)
elif result == 5:
what_to_do_result(result + 1)
else:
return True
I have started writing a test file called test_ninjapy and wrote some unittest. I do use Pytest.
import pytest
class MyTestException(Exception):
pass
def run_side_effect(*args, **kwargs):
raise MyTestException(kwargs["result"])
#pytest.fixture(name="resource")
def setup_fixture():
# Some code here
class TestNinja:
#staticmethod
def setup_method():
# Function called before each test
#staticmethod
def teardown_method():
# Function called after each test
#staticmethod
def test_my_function(mocker, resource):
# How to do this ???
mocker.patch("ninja.what_to_do_result", return_value=None, side_effect=run_side_effect)
# Then the test
assert 1 == 1 # -> This works
with pytest.raises(MyTestException):
ninja_function(a=1, b=2)
assert ninja_function(a=5, b=10)
The point is that I want to mock the function ninja.what_to_do_result and apply a side effect (= run a function).
I want the side effect to use the parameter (kwargs) or the function what_to_do_result.
But I don't know how to do this.
For example:
Because there are multiple possibilities (in the step 2, the call of what_to_do_result could be with 3 & 5, which are linked with 2 differents use cases I wxant to test.
Can you help me?
I did not found the related section in the documentation below.
Link to the documentation: https://github.com/pytest-dev/pytest-mock
I have python code as below
def call():
input1 = input('Bot1:')
input2 = input('Bot2:')
call()
input1
How to call 'input1' action only. I want after call it, the input1 action will start for inputting data on the screen.
But on above code... when I run, it show warning 'input1 not defined'
Thanks you!
You can't access the local variables of a function from outside of it. One way to workaround that limitation would be to do something like this:
ACTION1, ACTION2 = 1, 2
def get_input(action):
if action == ACTION1:
return input('Bot1:')
elif action == ACTION2:
return input('Bot2:')
else:
raise RuntimeError('Unknown action')
input1 = get_input(ACTION1)
I am trying to set/unset some of the debug flags while my code is running. Below is the snippet of the function
class ABC:
def __init__(self,debugFlag):
self.debugFlag = False
def some_function()
if self.debugFlag is True:
print "Some debug logs"
Above is the code snippet. I want to set this debugFlag while my program is running and depends on the situation want to set/unset its value. Based on the current value of debugFlag it should print debug logs or not
How to do this in python
Explaining my problem again : Suppose I am having a script that takes 60 mins to run. I executed the script with debugFlag False. After 15 mins, I want to enable the debug logs. How can I do this without interrupting my execution.
How about:
class ABC:
def __init__(self,debugFlag):
self.debugFlag = False
def some_function():
if self.debugFlag is True:
print "Some debug logs"
def set_flag():
self.debugFlag = True
You can change the value of self.debugFlag when a condition is met, yes.
class ABC:
def __init__(self,debugFlag):
self.debugFlag = debugFlag # or omit that arg and always false
def some_function(self): # Need self
if self.debugFlag:
print "Some debug logs"
def condition_setter(self):
# Do some checks here then set debugflag to False
self.debugFlag = False
One way to accomplish this is to declare var in your modules root, and import/reference them in the same scope when you set and reference.
Imagine the directory structure of your modules like so
my_module/
- __init__.py
- another_module.py
- utils/
- __init__.py
- and_so_on.py
in my_module/__init__.py declare your __debug__ var
__debug__ = False
In your example code
import my_module
class ABC:
def __init__(self):
pass
def some_function()
if my_module.__debug__ is True:
print "Some debug logs"
Then before you actually execute the code, set your debug flag to False importing and referencing in the same fashion
import my_module
my_module.__debug__ = True
As long as you import and reference the variable the same IE:
import my_module
if my_module.__debug__ is True:
print("IN DEBUG")
It will retain its value throughout your execution
Try something like this :
class ABC():
def __init__(self, debugFlag):
self.debugFlag = debugFlag
def some_function(self):
if self.debugFlag:
print('Debug on\n')
else:
print('Debug off\n')
abc_object = ABC(False)
def check_choice():
if str(choice) == '1':
abc_object.debugFlag = True
abc_object.some_function()
elif str(choice) == '2':
abc_object.debugFlag = False
abc_object.some_function()
else :
print('Invalid input')
while True:
choice = input('Type 1 to enable debugging, 2 to disable debuigging : ')
check_choice()
Summary:
When you initialize the class it takes 1 mandatory argument debugFlag, either True or False.
When you define a function from within the class you should use the 'self' argument.
Explanation as to of why this is
'if self.debugFlag' is the same as if 'self.debugFlag is True :' The former should be used as it is more concise.
We instantiate an instance of ABC and store it in the variable abc_object. We pass it a default value for debugFlag, in this case False.
We then introduce some logic to check the state of debugFlag, and then perform some function based on the outcome of our logic.
Hope this helps. Let me know if you need further clarification.
I dont think you can do this directly from variables, but you can, for example, create a file (debug.txt for example) and check if it exists for your triggering. For example, create an empty file called debug.txt and check, inside your script, if the file exists.
Untested code:
import os
class ABC:
def __init__(self,debugFlag):
self.debugFlag = False
def some_function()
if os.path.exists("debug.txt"):
print "Some debug logs"
This way you can trigger/untrigger debug by creating/deleting the file "debug.txt".
With a slight modification of your class:
class ABC:
def __init__(self,debugFlag=False):
self.debugFlag = debugFlag # initialize the flag here or use default
def some_function()
if self.debugFlag is True:
print "Some debug logs"
After you create the object you will be able to change its attributes, like:
obj_abc = ABC() # debug off by default
obj_abc.some_function() # no debug print
obj_abc.debugFlag = True # enable debug
obj_abc.some_function() # now with debug print
obj_abc.debugFlag = False # disable debug
obj_abc.some_function() # now without debug print
I have a class:
class AccountBusiness:
def save(self, account) -> Account:
if not account.account_number_is_valid():
return False
return True
and a test as:
#mock.patch.object(AccountBusiness, 'save')
def test_can_save_valid_account(self, mock_save):
mock_account = mock.create_autospec(Account)
mock_account.account_number_is_valid.return_value = False
account_business = AccountBusiness()
result = account_business.save(mock_account)
self.assertEqual(result.return_value, True)
but it shows an exception like:
AssertionError: <MagicMock name='save()()' id='48830448'> != True
I want to set the return value of account.account_number_is_valid() to False and run the test.
You are using a patch object on the instance method you are looking to test. However, you are looking to test the logic inside the save method. So mocking that out will not test any of the logic inside that method. So, the output you are actually getting here:
AssertionError: <MagicMock name='save()()' id='48830448'> != True
Should be the first hint that something is not right. Your save method is coming back as a MagicMock. You don't want this. What you actually want to do is only mock the Account class, and go accordingly from there. So, your patching here:
#mock.patch.object(AccountBusiness, 'save')
should actually only be:
#mock.patch('path.to.AccountBusiness.Account', return_value=Mock(), autospec=True)
The path.to.AccountBusiness.Account is the location of the Account class with respect to the AccountBusiness class.
So, with that patching, then the return_value of calling Account will now be your mock object that you can use for your account_number_is_valid. So, the code will actually look like this:
class MyTest(unittest.TestCase):
def setUp(self):
self.account_business = AccountBusiness()
#mock.patch('path.to.AccountBusiness.Account', return_value=Mock(), autospec=True)
def test_can_save_valid_account(self, mock_account):
mock_account_obj = mock_account.return_value
mock_account_obj.account_number_is_valid.return_value = False
self.assertFalse(self.account_business.save(mock_account_obj))
Also, pay close attention to the assertion at the end. It was changed to make use of the available assertFalse. Also, look over your own logic, as returning False for account_number_is_valid will actually return False in your save method.
Sorry the title isn't very clear but it is kind of hard to explain. So I am wondering how you can have a certain action happen within every single function of a python file. I want a user to type 'paper' inside any function in the entire python file and I cannot figure out how to do it. Here is an example:
def a():
raw_input()
print "Test"
def b():
raw_input()
print "Test 2"
How can I have it setup so a user can type 'paper' in these two functions (realistically more than 30+) and then it would print the statement "you have a paper"
Thank you so much for the help!
If you have something you want to apply to every function, you should use a decorator. I'm not exactly sure what you're trying to accomplish, but this should demonstrate:
>>> def youhaveapaper(function):
def wrapper(*args):
response = input('whatchu got?\n>>> ')
if response == 'paper':
print('you have a paper')
return function(*args)
import functools
functools.update_wrapper(wrapper, function)
return wrapper
>>> #youhaveapaper
def somefunction(x):
"""return the square of x"""
return x**2
>>> y = somefunction(5)
whatchu got?
>>> paper
you have a paper
>>> y
25
As you can see, somefunction did not need to be changed, it just needed #youhaveapaper placed before the definition.
Please see the good comments and questions above. Do you mean this:
#!/usr/bin/python
def paper(prompt):
response = raw_input(prompt+' ')
print('you have a {}'.format(response))
def a():
paper('Test')
def b():
paper('Test2')
a()
b()