Problem statement : I want to pass value returned by one function to another function from my test file.
test_abc.py
#pytest.fixture(scope='function')
def hold_value():
def _value(resp):
return resp
return _value
#when(parsers.cfparse('user did something with value "{a}" and "{b}" and “{c}"'))
def func1(hold_value, a, b, c):
response = do_something(a,b,c)
hold_value(response)
#then('user validate if above step is correct')
def func2(hold_value):
call_another_func_and_pass_above_response(hold_value)=> what can I do here to get value from fixture
This is test file where I tried creating fixture to hold value returned by one function and then use it in other functions
I am not sure, if it is right way of doing this, I want to pass values from one test step to another.
Can anyone please guide me to achieve desired result
I am able to achieve solution by using context as a fixture
#pytest.fixture(scope='function')
def context():
return {}
#when(parsers.cfparse('user did something with value "{a}" and "{b}" and “{c}"'))
def func1(context, a, b, c):
response = do_something(a,b,c)
context[‘response’] = response
#then('user validate if above step is correct')
def func2(context):
call_another_func_and_pass_above_response(context.get(‘response’))
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 this function that I wish to test, this is how it looks like.
def myfunction():
response = requests.post(url,params=params,headers=headers,data=data)
response = response.json()
return response["Findme"].lower()
My test script:
#mock.patch('requests.post',return_value="{'Findme': 'test'}")
def test_myfunction(mocked_post):
**assert myfunction() == "test"**
When i run the test, i keep getting None for myfunction(), but when i remove the response.json() it works?
Please can anyone assist me.
As mentioned by Deep Space, your returned object does not have a json method, as it is of type str. If you want to have the same behavior as in the tested function, you have to provide an object with that method:
class MockResponse:
"""Mocks relevant part of requests.Response"""
def __init__(self, s):
self.json_string = s
def json(self):
return json.loads(self.json_string)
#mock.patch("requests.post", return_value=MockResponse('{"Findme": "test"}'))
def test_myfunction(mocked_post):
assert myfunction() == "test"
This way, an object of type MockResponse is returned from the mocked post function, that can be deserialized using json().
You could also mock the return value of json directly instead of mocking the return value of post, if you want to do this. In this case you wouldn't need an extra class:
#mock.patch("requests.post")
def test_myfunction(mocked_post):
mocked_post.return_value.json.return_value = {"Findme": "test"}
assert myfunction() == "test"
one input
one output
I want to get output through one long process.Because the process is so long, I have to continue input and return output. Is there some convenient way to get output inside the class or function without pass one function and other?
the demo function as follows:
main.py
from run import class1
def f1(input):
c=class1()
output=c.cf2(input)
return output
run.py
class1(input):
def cf1(input):
ca=class2()
output=ca.c2f1(input)
return output
def cf2(input):
output=self.cf1(input)
return output
class2():
def c2f1(user_input):
variable=user_input
output=self.c2f2(variable)
return output
def c2f2():
y=…
return y
I am a beginner in Python and I need some help on decorators. I am writing a few methods which call other methods that are generated using swagger. Basically all these swagger methods have GET APIs. All I need to do in my code is to call those swagger methods and return the value. I am looking for ways to optimize this instead of writing the same kind of method for each API. I came across decorators which can be used in this case. But my implementation is not giving the desired result
def get_component_info(self, func):
def inner():
data = None
try:
ret = func()
if ret.status == 200:
log.info('ret ' + str(ret))
else:
logging.error('Error: ' + str(ret.text))
except Exception as e:
logging.error(" failed with error " + str(e.reason) +
" and error code " + str(e.status))
finally:
return data
return inner()
def get_firewall_info(self):
return self._monitor.list_firewall_monitors_with_http_info() <-- swagger method
def get_firewall_info_caller(self):
get_firewall_info = self.get_component_info(self.get_firewall_info())
But the above implementation always return None because it never executes self._monitor.list_firewall_monitors_with_http_info(), but the test isn't failing
If you help me fix this, then I can use the same for getting server info, auth info, network info, etc. If decorators can't be used, what else I can use to optimize this..?
Thanks
Decorators are usually functions which take a second function as an argument and then define and return a third function which calls the second function while changing its input and/or output. It looks like you have a better handle on this than I did as a beginner.
def decorator(func):
def inner(*args, **kwargs):
# Do stuff here...
value = func(*args, **kwargs)
# ...or here.
return value
return inner
The only change I would recommend to your decorator is not to call inner and return the result, but to return the function itself. When you make this change you'll have to call the function you are returning now after it is returned.
def get_component_info(self, func):
def inner():
# ...
return inner
def get_firewall_info_caller(self):
# You will now want to call the `inner` function after you get
# it from `get_component_info`.
get_firewall_info = self.get_component_info(...)()
It looks like the core of your bug is that you aren't providing a function to get_component_info; you're providing the result of calling that function. I think that changing the code to not call get_firewall_info should fix your code.
def get_firewall_info_caller(self):
# You don't want to call the function you're providing to a
# decorator, since it's expecting the function not the result.
get_firewall_info = self.get_component_info(self.get_firewall_info)()
I resolved it as shown below. Not sure if it is the right approach. Please correct me
def get_component_info(self, func):
def inner():
data = None
try:
ret = func()
if ret.status == 200:
log.info('ret ' + str(ret))
else:
logging.error('Error: ' + str(ret.text))
except Exception as e:
logging.error(" failed with error " + str(e.reason) +
" and error code " + str(e.status))
finally:
return data
return inner
def get_firewall_info(self):
data = self.get_component_info(self._monitor.list_firewall_monitors_with_http_info)()
return data
I am making up a handler to handle different types of data. Here is my current solution:
def get_handler_by_type(type):
def handler_for_type_A:
...
#code for processing data type A
def handler_for_type_B:
...
#code for processing data type B
def handler_for_type_C:
...
#code for processing data type C
handler_map = {type_A: handler_for_type_A,
type_B: handler_for_type_B,
type_C: handler_for_type_C,
}
return handler_map(type)
However, this seems quite inefficient as I will call get_handler_by_type frequently and every time it gets called, the dictionary will be constructed again.
I know I could do this instead:
def handler_for_type_A:
...
#code for processing data type A
def handler_for_type_B:
...
#code for processing data type B
def handler_for_type_C:
...
#code for processing data type C
handler_map = {type_A: handler_for_type_A,
type_B: handler_for_type_B,
type_C: handler_for_type_C,
}
def get_handler_by_type(type, handler_map = handler_map):
return handler_map(type)
But this is pretty ugly in my opinion. Because I have handler_for_type_Xs and handler_map that are polluting the global space. Is there a way of doing this both efficiently and elegantly?
Thanks for any inputs.
One way is to look the handler up dynamically (if you have a consistent naming convention)
return vars()['handler_for_'+type]
Another way is to store the map as an attribute of the function
def get_handler_by_type(type):
def handler_for_type_A:
...
#code for processing data type A
def handler_for_type_B:
...
#code for processing data type B
def handler_for_type_C:
...
#code for processing data type C
if not hasattr(get_handler_by_type, 'handler_map'):
get_handler_by_type.handler_map = {'type_A': handler_for_type_A,
'type_B': handler_for_type_B,
'type_C': handler_for_type_C,
}
return get_handler_by_type.handler_map[type]
This way will encapsulate it:
def _handler_helper():
def fna():
print "a"
pass
def fnb():
print "b"
pass
m = {"a":fna,"b":fnb}
return lambda x:m[x]
get_handler_by_type = _handler_helper()
You may want to use def if you want to have a docstring, but this works.
Another option might be to have a more OOP approach:
class _HandlerHelper:
def fna(self):
print 'a'
def fnb(self):
print 'b'
# __call__ is a magic method which lets you treat the object as a function
def __call__(self, fn):
return getattr(self, 'fn' + fn)
get_handler_by_type = _HandlerHelper()