There are several unit test frameworks available in Python. Try/except blocks are good for error handling, but you still need a separate unit test around the call if you want to unit test it.
You do have something you can test, you can just return it and test that in your unit test.
Example Unit test using unittest:
import unittest
import requests
class RestCalls():
def google_do_something(blahblah):
url= blahblah
try:
r = requests.get(url,timeout=1)
r.raise_for_status()
return r.status_code
except requests.exceptions.Timeout as errt:
print (errt)
raise
except requests.exceptions.HTTPError as errh:
print (errh)
raise
except requests.exceptions.ConnectionError as errc:
print (errc)
raise
except requests.exceptions.RequestException as err:
print (err)
raise
class TestRESTMethods(unittest.TestCase):
def test_valid_url(self):
self.assertEqual(200,RestCalls.google_do_something('http://www.google.com/search'))
def test_exception(self):
self.assertRaises(requests.exceptions.Timeout,RestCalls.google_do_something,'http://localhost:28989')
if __name__ == '__main__':
unittest.main()
Executing should show (made some edits to this post, updated output included at bottom of post):
> python .\Tests.py
.
----------------------------------------------------------------------
Ran 1 test in 0.192s
OK
If you asserted a different response code from your request, it would fail (the request is just returning http response codes):
python .\Tests.py
F
======================================================================
FAIL: test_upper (__main__.TestStringMethods)
----------------------------------------------------------------------
Traceback (most recent call last):
File ".\Tests.py", line 25, in test_upper
self.assertEqual(404,RestCalls.google_do_something('search'))
AssertionError: 404 != 200
----------------------------------------------------------------------
Ran 1 test in 0.245s
FAILED (failures=1)
Which is expected.
Edit: Included exception testing. You can test these by just including raise in the except block, which will show this after running:
> python .\Tests.py
HTTPConnectionPool(host='localhost', port=28989): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x03688598>, 'Connection to localhost timed out. (connect timeout=1)'))
..
----------------------------------------------------------------------
Ran 2 tests in 2.216s
OK
References:
- Unit tests in Python
- https://docs.python.org/3/library/unittest.html
- https://en.wikipedia.org/wiki/List_of_HTTP_status_codes
There are several unit test frameworks available in Python. Try/except blocks are good for error handling, but you still need a separate unit test around the call if you want to unit test it.
You do have something you can test, you can just return it and test that in your unit test.
Example Unit test using unittest:
import unittest
import requests
class RestCalls():
def google_do_something(blahblah):
url= blahblah
try:
r = requests.get(url,timeout=1)
r.raise_for_status()
return r.status_code
except requests.exceptions.Timeout as errt:
print (errt)
raise
except requests.exceptions.HTTPError as errh:
print (errh)
raise
except requests.exceptions.ConnectionError as errc:
print (errc)
raise
except requests.exceptions.RequestException as err:
print (err)
raise
class TestRESTMethods(unittest.TestCase):
def test_valid_url(self):
self.assertEqual(200,RestCalls.google_do_something('http://www.google.com/search'))
def test_exception(self):
self.assertRaises(requests.exceptions.Timeout,RestCalls.google_do_something,'http://localhost:28989')
if __name__ == '__main__':
unittest.main()
Executing should show (made some edits to this post, updated output included at bottom of post):
> python .\Tests.py
.
----------------------------------------------------------------------
Ran 1 test in 0.192s
OK
If you asserted a different response code from your request, it would fail (the request is just returning http response codes):
python .\Tests.py
F
======================================================================
FAIL: test_upper (__main__.TestStringMethods)
----------------------------------------------------------------------
Traceback (most recent call last):
File ".\Tests.py", line 25, in test_upper
self.assertEqual(404,RestCalls.google_do_something('search'))
AssertionError: 404 != 200
----------------------------------------------------------------------
Ran 1 test in 0.245s
FAILED (failures=1)
Which is expected.
Edit: Included exception testing. You can test these by just including raise in the except block, which will show this after running:
> python .\Tests.py
HTTPConnectionPool(host='localhost', port=28989): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x03688598>, 'Connection to localhost timed out. (connect timeout=1)'))
..
----------------------------------------------------------------------
Ran 2 tests in 2.216s
OK
References:
- Unit tests in Python
- https://docs.python.org/3/library/unittest.html
- https://en.wikipedia.org/wiki/List_of_HTTP_status_codes
I am not sure that your approach is such a good idea (just printing something in case of an error) but you could mock the print function to see if it was really called (and with what arguments):
https://docs.python.org/3/library/unittest.mock.html?highlight=mock#module-unittest.mock
Edit:
Working with mocks is a bit tricky as far as I remember. You would have to mock the print function in the current module. Perhaps something like this (not tested ...):
from unittest.mock import patch
from unittest import TestCase
class TestGoogleDoSomething(TestCase)
@patch("nameOfYourModule.print")
def test_google_do_something(self, print_mock): # the decorator will pass the mock object into the function
g = google_do_something('blahblah')
print_mock.assert_called_with("your error message here ...")
python - How to write a unit test code for functions which make API requests to web? - Stack Overflow
unit testing - How do I test an API Client with Python? - Stack Overflow
How to unit test a service which makes multiple external api calls
How to test an API request to the external system
Videos
I would personally do it by first creating a single interface or function call which your library uses to actually contact the service, then write a custom mock for that during tests.
For example, if the service uses HTTP and you're using Requests to contact the service:
class MyClient(…):
def do_stuff(self):
result = requests.get(self.service_url + "/stuff")
return result.json()
I would first write a small wrapper around requests:
class MyClient(…):
def _do_get(self, suffix):
return requests.get(self.service_url + "/" + suffix).json()
def do_stuff(self):
return self._do_get("stuff")
Then, for tests, I would mock out the relevant functions:
class MyClientWithMocks(MyClient):
def _do_get(self, suffix):
self.request_log.append(suffix)
return self.send_result
And use it in tests like this:
def test_stuff(self):
client = MyClientWithMocks(send_result="bar")
assert_equal(client.do_stuff(), "bar")
assert_contains(client.request_log, "stuff")
Additionally, it would likely be advantageous to write your tests so that you can run them both against your mock and against the real service, so that if things start failing, you can quickly figure out who's fault it is.
I'm using HTTmock and I'm pretty happy with it : https://github.com/patrys/httmock