How to fetch and assert and REST API in Python Unittests? - python-2.7

while trying to fetch and assert a REST API, throwing a "TypeError". The following is the code which I am running
def test_get_action(self):
action_id = self._get_action_id()
"""Get actions, Successful with response status 200"""
resp = self.test_client.get_action(action_id)
self.assertEqual(resp.response['status'], '200')
self.assertEqual(resp.values()[0][0]['action_id'], action_id)
And I'm seeing the error as "TypeError: 'dict_values' object does not support indexing"
Further investigations:
* Running this test in Python 2.7 and seeing the above error
* I change the code differently as follow, but not able to derive this.
self.assertListEqual(resp.values()[0][0]['action_id'], action_id)
self. assertSequenceEqual(resp.values()[0][0]['action_id'], action_id)
I'm new to Python and unittests, please help.
Thanks in advance.

The error message suggests that resp.values() is returning a dict_values object rather than a list.
Try wrapping the call to resp.values() in a call to list():
self.assertEqual(list(resp.values())[0][0]['action_id'], action_id)

Related

Additional arguments in Flask grequests hook

I am having issue in passing additional parameter to grequests using a hook, Its working in a standalone app (non flask) but its not with flask (flask integrated server) Here is my code snippet.
self.async_list = []
for url in self.urls:
self.action_item = grequests.get(url, hooks = {'response' : [self.hook_factory(test='new_folder')]}, proxies={ 'http': 'proxy url'},timeout=20)
self.async_list.append(self.action_item)
grequests.map(self.async_list)
def hook_factory(self, test, *factory_args, **factory_kwargs):
print (test + "In start of hook factory") #this worked and I see test value is printing as new_folder
def do_something(response, *args, **kwargs):
print (test + "In do something") #This is not working hence I was not able to save this response to a newly created folder.
self.file_name = "str(test)+"/"
print ("file name is " + self.file_name)
with open(REL_PATH + self.file_name, 'wb') as f:
f.write(response.content)
return None
return do_something
Am I missing anything here?.
Trying to answer my own question, After further analysis there was nothing wrong with the above code, for some reason I was not getting my session data which is in the request_ctx_stack.top. But the same session data was available in my h_request_ctx_stack._local, Don't know the reason. But I was able to get my data from h_request_ctx_stack._local instead _request_ctx_stack.top for this hook alone. After I made that change was able execute the same hook without any issues.

request issue when unit-testing webapp2 with mock and patch

I'm building unit tests for this webapp2 handler (built for GAE)
class PushNotificationHandler(webapp2.RequestHandler):
def post(self):
UserNotification.parse_from_queue(self.request)
return
app = webapp2.WSGIApplication([
(r'/push/notification', PushNotificationHandler),
], debug=True)
One test is
#patch.object(UserNotification, 'parse_from_queue')
def test_post_webapp(self, p_parse_from_queue):
response = webtest.TestApp(app).post('/push/notification')
eq_(response.status_int, 200)
p_parse_from_queue.assert_called_once_with(response.request)
The HTTP reply is OK, but the mock assertion fails:
Expected call: parse_from_queue(<TestRequest at 0x105a89850 POST http://localhost/push/notification>)
Actual call: parse_from_queue(<Request at 0x105a89950 POST http://localhost/push/notification>)
I can't understand why the request is not the correct one (looks like a deep copy). Is there anything wrong with the unit-test, or is that the way webapp2 handle requests. In the second case, is there a way to test it, without creating a separate test to test PushNotificationHandler.post()
Thanks
I've used mock's call_args in a similar situation. You can do something like this:
request = p_parse_from_queue.call_args[0][0]
self.assertEqual(request.url, "foo")
self.assertEqual(request.*, *)
The [0][0] gives you the first passed argument assuming that you are using ordered arguments and not keyword arguments.
You can then proceed to check other relevant attributes of the request object to make sure it is behaving as expected.

Assert that logging has been called with specific string

I'm trying to use unittest to test some functions of a SimpleXMLRPCServer I made. Togethere with Mock, I'm now trying to assert that a specific message has been logged when an if statement is reached, but I can't get it to work. I've tried implementing various answers I found here on StackOverflow or by Googling, but still no luck. The calls I make in the Test Case are as follows:
def test_listen_for_tasks(self):
el = {'release': 'default', 'component': None}
for i in range(50):
self.server._queue.put(el)
ServerThread.listen_for_tasks(self.server, 'bla', 'blabla')
with mock.patch('queue_server.logging') as mock_logging:
mock_logging.warning.assert_called_with('There are currently {}'
' items in the queue'.format(
str(len(self.server._queue.queue))))
The function in the server is as follows:
def listen_for_tasks(self, release, component):
item = {'release': release, 'component': component}
for el in list(self._queue.queue):
if self.is_request_duplicate(el, item):
logger.debug('Already have a request'
' for this component: {}'.format(item))
return
self._queue.put(item, False)
if len(self._queue.queue) > 50:
logger.warning('There are currently {}'
' items in the queue'.format(
str(len(self._queue.queue))))
Any idea why this is not working? I'm new to unit testing in Python and asserting that a logger has done something seems the biggest problem one could face, so I might have screwed up with something really simple in the code. Any kind of help will be greatly appreciated!
EDIT: for completeness, here's the test output and failure:
.No handlers could be found for logger "queue_server"
F
FAIL: test_listen_for_tasks (__main__.TestQueueServer)
Traceback (most recent call last):
File "artifacts_generator/test_queue_server.py", line 46, in test_listen_for_tasks
str(len(self.server._queue.queue))))
File "/home/lugiorgi/Desktop/Code/publisher/env/local/lib/python2.7/site-packages/mock/mock.py", line 925, in assert_called_with
raise AssertionError('Expected call: %s\nNot called' % (expected,))
AssertionError: Expected call: warning('There are currently 51 items in the queue')
Not called
Ran 2 tests in 0.137s
FAILED (failures=1)
Since python 3.4 you can use unittest.TestCase class method assertLogs
import logging
import unittest
class LoggingTestCase(unittest.TestCase):
def test_logging(self):
with self.assertLogs(level='INFO') as log:
logging.info('Log message')
self.assertEqual(len(log.output), 1)
self.assertEqual(len(log.records), 1)
self.assertIn('Log message', log.output[0])
You need to first mock the object, then call the function you want to test.
When mocking the object, you also need to provide the full package and object/function name of the object you are mocking, not a variable name.
Finally, it's often more convenient to use the decorator form of patch.
So, for example:
logger = logging.getLogger(__name__)
def my_fancy_function():
logger.warning('test')
#patch('logging.Logger.warning')
def test_my_fancy_function(mock):
my_fancy_function()
mock.assert_called_with('test')
# if you insist on using with:
def test_my_fancy_function_with_with():
with patch('logging.Logger.warning') as mock:
my_fancy_function()
mock.assert_called_with('test')

problems for parse complicate json post data in django

I have a django parse function as:
def parse_org(request):
try:
org = simplejson.loads(request.POST['org'])
except Exception:
traceback.print_exc()
print org
I got the decode error.
On the client side, the script version(code are pasted in later part) works fine, but recently I want to write a python version to do load test, so I write the following code in a python client script to send request:
data_dict = {}
org = ["UCSD", "MIT"]
data_dict["org"] = org
req = urllib2.Request(request_url, urllib.urlencode(data_dict), headers)
response = urllib2.urlopen(req, timeout = 5)
Then the parse code at the django site gets parsing error. I compare the correct javascript version and the wrong python clients, the only difference is the single and double quote,
the wrong parsed input at django side is:
POST:<QueryDict: {u'org': [u"['UCSD', 'MIT']"], ....
the correct input is:
POST:<QueryDict: {u'org': [u'["UCSD","MIT"]'], ....
For your reference, the javascript side looks like(the django can correctly parse the org as array):
var org = [];
org.push("UCSD")
org.push("MIT")
var data = {"org": JSON.stringify(org), ...
}
$.post(url, data, function(data){
callback(data);
});
I searched a lot, but still can't find why the python client can't work but the javascript client can work. Is it related with the urllib's urlencode? and why there is single and double quote difference there?
Thanks a lot!

Grails - No class def found error when calling web service

Updated to reflect new error message after changes
Howdy, I am trying to call a web service from Grails, but keep running in to errors.
Here's what my class looks like:
import groovyx.net.ws.WSClient
...
def serviceUrl = "http://www.w3schools.com/webservices/tempconvert.asmx?WSDL"
def proxy = new WSClient(serviceUrl.toString(), this.class.classLoader)
serviceResult = proxy.FahrenheitToCelsius("80")
println serviceResult
...
I am encountering a grails runtime exception:
Error 500: Executing action [index] of controller [myPackage.myController] caused exception: java.lang.NoClassDefFoundError: org/apache/cxf/endpoint/Client
Have been trying to troubleshoot, but have been unable to find any helpful resources. Any help or suggestions on how to remedy would be much appreciated.
Thanks.
You missed the new operator it looks like:
def proxy = new WSClient(serviceUrl.toString(), this.class.classLoader)