Skip to content
Snippets Groups Projects
Commit 92891386 authored by Fynn Becker's avatar Fynn Becker :crab:
Browse files

Close #9 Add tests

parent caeedf26
No related branches found
No related tags found
No related merge requests found
...@@ -212,3 +212,9 @@ def your_callback_func(sender, **kwargs): ...@@ -212,3 +212,9 @@ def your_callback_func(sender, **kwargs):
``` ```
For more information on signals refer to the django docs. They are great. Really. For more information on signals refer to the django docs. They are great. Really.
### Testing
`postgrestutils` has a bunch of unittests because manually testing it has become quite time-consuming.
The tests aim to ensure functional correctness as well as some performance related concerns i.e. caching and lazyness.
With `requests-mock` installed, running is as easy as `python -m unittest`.
import datetime
from unittest import TestCase
from requests_mock import Mocker
from postgrestutils.client import (
Count, MultipleObjectsReturned, ObjectDoesNotExist,
)
from postgrestutils.client.postgrestclient import LazyPostgrestJsonResult
TOKEN = 'JWT_token'
DEFAULT_HEADERS = {
'Authorization': 'Bearer {}'.format(TOKEN),
'Accept': 'application/json'
}
SUPERHERO_TEST_DATA = [
{
'id': 68,
'name': 'Batman',
'gender': 'Male',
'eye_color': 'blue',
'race': 'Human',
'hair_color': 'black',
'height': 188,
'publisher': 'DC Comics',
'skin_color': None,
'alignment': 'good',
'weight': 95
}, {
'id': 212,
'name': 'Deadpool',
'gender': 'Male',
'eye_color': 'brown',
'race': 'Mutant',
'hair_color': 'No Hair',
'height': 188,
'publisher': 'Marvel Comics',
'skin_color': None,
'alignment': 'neutral',
'weight': 95
}, {
'id': 345,
'name': 'Iron Man',
'gender': 'Male',
'eye_color': 'blue',
'race': 'Human',
'hair_color': 'Black',
'height': 198,
'publisher': 'Marvel Comics',
'skin_color': None,
'alignment': 'good',
'weight': 191
}, {
'id': 369,
'name': 'Joker',
'gender': 'Male',
'eye_color': 'green',
'race': 'Human',
'hair_color': 'Green',
'height': 196,
'publisher': 'DC Comics',
'skin_color': 'white',
'alignment': 'bad',
'weight': 86
}, {
'id': 423,
'name': 'Magneto',
'gender': 'Male',
'eye_color': 'grey',
'race': 'Mutant',
'hair_color': 'White',
'height': 188,
'publisher': 'Marvel Comics',
'skin_color': None,
'alignment': 'bad',
'weight': 86
}
]
@Mocker()
class TestPgrestClientGet(TestCase):
def setUp(self):
super().setUp()
from postgrestutils.client import pgrest_client
pgrest_client.configure(TOKEN, base_uri='http://example.com/')
self.pgrest_client = pgrest_client
self.data = SUPERHERO_TEST_DATA[0]
def test_single_object_returned(self, mock):
mock.register_uri(
'GET',
'http://example.com/superhero?id=eq.1000000000',
request_headers={**DEFAULT_HEADERS, **{'Accept': 'application/vnd.pgrst.object+json'}},
status_code=200,
reason='OK',
json=self.data
)
params = {'id': 'eq.1000000000'}
res = self.pgrest_client.get('superhero', params=params)
self.assertDictEqual(res, self.data)
self.assertTrue(mock.called_once)
def test_object_does_not_exist(self, mock):
mock.register_uri(
'GET',
'http://example.com/superhero?id=eq.1337',
request_headers={**DEFAULT_HEADERS, **{'Accept': 'application/vnd.pgrst.object+json'}},
status_code=406,
reason='Not Acceptable',
text="""{"details":"Results contain 0 rows, application/vnd.pgrst.object+json requires 1 row","message":"""
""""JSON object requested, multiple (or no) rows returned"}"""
)
params = {'id': 'eq.1337'}
with self.assertRaises(ObjectDoesNotExist):
self.pgrest_client.get('superhero', params=params)
self.assertTrue(mock.called_once)
def test_multiple_objects_returned(self, mock):
mock.register_uri(
'GET',
'http://example.com/superhero',
request_headers={**DEFAULT_HEADERS, **{'Accept': 'application/vnd.pgrst.object+json'}},
status_code=406,
reason='Not Acceptable',
text="""{"details":"Results contain 5 rows, application/vnd.pgrst.object+json requires 1 row","message":"""
""""JSON object requested, multiple (or no) rows returned"}"""
)
with self.assertRaises(MultipleObjectsReturned):
self.pgrest_client.get('superhero')
self.assertTrue(mock.called_once)
def test_datetime_parser(self, mock):
expected = {
'id': 1337,
'random': datetime.datetime(2020, 5, 20, 8, 35, 6, 659425, tzinfo=datetime.timezone.utc)
}
mock.register_uri(
'GET',
'http://example.com/random_datetime',
request_headers={**DEFAULT_HEADERS, **{'Accept': 'application/vnd.pgrst.object+json'}},
status_code=200,
reason='OK',
json={'id': 1337, 'random': "2020-05-20T08:35:06.659425+00:00"}
)
params = {'id': 'eq.1337'}
res = self.pgrest_client.get('random_datetime', params=params)
self.assertDictEqual(res, expected)
self.assertTrue(mock.called_once)
def test_without_datetime_parser(self, mock):
test_json = {'id': 1337, 'random': "2020-05-20T08:35:06.659425+00:00"}
mock.register_uri(
'GET',
'http://example.com/random_datetime',
request_headers={**DEFAULT_HEADERS, **{'Accept': 'application/vnd.pgrst.object+json'}},
status_code=200,
reason='OK',
json=test_json
)
params = {'select': 'id,random', 'id': 'eq.1337'}
res = self.pgrest_client.get('random_datetime', params=params, parse_dt=False)
self.assertDictEqual(res, test_json)
self.assertTrue(mock.called_once)
@Mocker()
class TestPgrestClientFilterStrategyNone(TestCase):
def setUp(self):
super().setUp()
from postgrestutils.client import pgrest_client
pgrest_client.configure(TOKEN, base_uri='http://example.com/')
self.pgrest_client = pgrest_client
self.data = SUPERHERO_TEST_DATA
def test_fetch_all_first(self, mock):
mock.register_uri(
'GET',
'http://example.com/superhero',
request_headers=DEFAULT_HEADERS,
status_code=200,
reason='OK',
json=self.data
)
res = self.pgrest_client.filter('superhero')
self.assertIsInstance(res, LazyPostgrestJsonResult) # should return lazy object
self.assertFalse(mock.called) # no request should have been made yet
self.assertListEqual(list(res), self.data) # fetch data
self.assertTrue(mock.called_once) # should have been called once
self.assertListEqual(res._result_cache, self.data) # fetched data should be cached
self.assertEqual(res._len_cache, len(self.data)) # len of fetched data should be cached
self.assertListEqual(list(res), self.data) # should utilize cache
self.assertListEqual(res[2:], self.data[2:]) # should utilize cache
self.assertDictEqual(res[0], self.data[0]) # should utilize cache
self.assertTrue(mock.called_once) # should not have been called again
def test_fetch_len_first(self, mock):
mock.register_uri(
'GET',
'http://example.com/superhero',
request_headers=DEFAULT_HEADERS,
status_code=200,
reason='OK',
json=self.data
)
res = self.pgrest_client.filter('superhero')
self.assertIsInstance(res, LazyPostgrestJsonResult) # should return lazy object
self.assertFalse(mock.called) # no request should have been made yet
self.assertEqual(len(res), len(self.data)) # should fetch len
self.assertTrue(mock.called_once) # should have been called once
self.assertEqual(res._len_cache, len(self.data)) # len of fetched data should be cached
self.assertListEqual(res._result_cache, self.data) # results should be cached (counting strategy none)
self.assertListEqual(res[2:], self.data[2:]) # should utilize cache
self.assertDictEqual(res[0], self.data[0]) # should utilize cache
self.assertListEqual(list(res), self.data) # should utilize cache
self.assertTrue(mock.called_once) # should not have been called again
@Mocker()
class TestPgrestClientFilterStrategyExact(TestCase):
def setUp(self):
super().setUp()
from postgrestutils.client import pgrest_client
pgrest_client.configure(TOKEN, base_uri='http://example.com/')
self.pgrest_client = pgrest_client
self.data = SUPERHERO_TEST_DATA
def test_fetch_all_first(self, mock):
# in order to fetch all
mock.register_uri(
'GET',
'http://example.com/superhero',
request_headers=DEFAULT_HEADERS,
status_code=200,
reason='OK',
json=self.data
)
res = self.pgrest_client.filter('superhero', count=Count.EXACT)
self.assertIsInstance(res, LazyPostgrestJsonResult) # should return lazy object
self.assertFalse(mock.called) # no request should have been made yet
self.assertListEqual(list(res), self.data) # fetch data
self.assertTrue(mock.called_once) # should have been called once
self.assertListEqual(res._result_cache, self.data) # fetched data should be cached
self.assertEqual(res._len_cache, len(self.data)) # len of fetched data should also be cached
self.assertListEqual(list(res), self.data) # should utilize cache
self.assertListEqual(res[2:], self.data[2:]) # should utilize cache
self.assertDictEqual(res[0], self.data[0]) # should utilize cache
self.assertTrue(mock.called_once) # should not have been called again
def test_fetch_len_first(self, mock):
# in order to fetch all
mock.register_uri(
'GET',
'http://example.com/superhero',
request_headers=DEFAULT_HEADERS,
status_code=200,
reason='OK',
json=self.data
)
# in order to fetch first
mock.register_uri(
'GET',
'http://example.com/superhero',
request_headers={**DEFAULT_HEADERS, **{'Range-Unit': 'items', 'Range': '0-0'}},
status_code=200,
reason='OK',
headers={'Content-Range': '0-0/*'},
json=self.data[0]
)
# in order to fetch range since index 2
mock.register_uri(
'GET',
'http://example.com/superhero',
request_headers={**DEFAULT_HEADERS, **{'Range-Unit': 'items', 'Range': '2-'}},
status_code=200,
reason='OK',
headers={'Content-Range': '2-4/*'},
json=self.data[2:]
)
# in order to fetch length
mock.register_uri(
'GET',
'http://example.com/superhero',
request_headers={**DEFAULT_HEADERS, **{'Range-Unit': 'items', 'Range': '0-0', 'Prefer': 'count=exact'}},
status_code=206,
reason='Partial Content',
headers={'Content-Range': '0-0/5'},
json=self.data[0]
)
res = self.pgrest_client.filter('superhero', count=Count.EXACT)
self.assertIsInstance(res, LazyPostgrestJsonResult) # should return lazy object
self.assertFalse(mock.called) # no request should have been made yet
self.assertEqual(len(res), len(self.data)) # should fetch len
self.assertTrue(mock.called_once) # should have been called once
self.assertEqual(res._len_cache, len(self.data)) # len of fetched data should be cached
self.assertListEqual(res[2:], self.data[2:]) # should fetch range starting at index 2
self.assertDictEqual(res[0], self.data[0]) # should fetch first element as range
self.assertListEqual(list(res), self.data) # should fetch all elements
self.assertListEqual(res._result_cache, self.data) # should cache all elements
self.assertTrue(mock.called) # should have been called at least once
self.assertEqual(mock.call_count, 4) # should have only been called 4 times (fetch len, range, first and all)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment