summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorJordan Cook <jordan.cook@pioneer.com>2022-04-20 16:50:40 -0500
committerJordan Cook <jordan.cook@pioneer.com>2022-04-22 17:28:33 -0500
commit0dbd82d4d28875f2c0a592dfc89f50bf1c63cb2b (patch)
treef3982671c81005c29c39fbd6da241e79509cc0cf /tests
parent57579af3a5c4e683f2dd96f493471077808d1d39 (diff)
downloadrequests-cache-0dbd82d4d28875f2c0a592dfc89f50bf1c63cb2b.tar.gz
Merge *PickleDict storage classes into parent classes
Diffstat (limited to 'tests')
-rw-r--r--tests/integration/base_cache_test.py10
-rw-r--r--tests/integration/base_storage_test.py30
-rw-r--r--tests/integration/test_dynamodb.py8
-rw-r--r--tests/integration/test_mongodb.py22
-rw-r--r--tests/integration/test_sqlite.py23
-rw-r--r--tests/unit/test_base_cache.py6
-rw-r--r--tests/unit/test_session.py10
7 files changed, 48 insertions, 61 deletions
diff --git a/tests/integration/base_cache_test.py b/tests/integration/base_cache_test.py
index 081b5a1..6d71018 100644
--- a/tests/integration/base_cache_test.py
+++ b/tests/integration/base_cache_test.py
@@ -44,6 +44,7 @@ logger = getLogger(__name__)
# Handle optional dependencies if they're not installed,
# so any skipped tests will explicitly be shown in pytest output
TEST_SERIALIZERS = SERIALIZERS.copy()
+TEST_SERIALIZERS['no_op'] = None
try:
TEST_SERIALIZERS['safe_pickle'] = safe_pickle_serializer(secret_key='hunter2')
except ImportError:
@@ -51,6 +52,10 @@ except ImportError:
VALIDATOR_HEADERS = [{'ETag': ETAG}, {'Last-Modified': LAST_MODIFIED}]
+def _valid_serializer(serializer) -> bool:
+ return isinstance(serializer, (SerializerPipeline, Stage)) or serializer is None
+
+
class BaseCacheTest:
"""Base class for testing cache backend classes"""
@@ -79,7 +84,7 @@ class BaseCacheTest:
"""Test all relevant combinations of (methods X data fields X serializers).
Requests with different request params, data, or json should be cached under different keys.
"""
- if not isinstance(serializer, (SerializerPipeline, Stage)):
+ if not _valid_serializer(serializer):
pytest.skip(f'Dependencies not installed for {serializer}')
url = httpbin(method.lower())
@@ -92,7 +97,7 @@ class BaseCacheTest:
@pytest.mark.parametrize('response_format', HTTPBIN_FORMATS)
def test_all_response_formats(self, response_format, serializer):
"""Test all relevant combinations of (response formats X serializers)"""
- if not isinstance(serializer, SerializerPipeline):
+ if not _valid_serializer(serializer):
pytest.skip(f'Dependencies not installed for {serializer}')
session = self.init_session(serializer=serializer)
@@ -311,6 +316,7 @@ class BaseCacheTest:
# Cache a response and some redirects, which should be the only non-expired cache items
session.get(httpbin('get'), expire_after=-1)
session.get(httpbin('redirect/3'), expire_after=-1)
+ assert len(session.cache.redirects.keys()) == 4
session.cache.remove_expired_responses()
assert len(session.cache.responses.keys()) == 2
diff --git a/tests/integration/base_storage_test.py b/tests/integration/base_storage_test.py
index 7d38643..ee3bf31 100644
--- a/tests/integration/base_storage_test.py
+++ b/tests/integration/base_storage_test.py
@@ -14,7 +14,6 @@ class BaseStorageTest:
storage_class: Type[BaseStorage] = None
init_kwargs: Dict = {}
- picklable: bool = False
num_instances: int = 10 # Max number of cache instances to test
def init_cache(self, cache_name=CACHE_NAME, index=0, clear=True, **kwargs):
@@ -98,21 +97,20 @@ class BaseStorageTest:
cache['key']
def test_picklable_dict(self):
- if self.picklable:
- cache = self.init_cache(serializer='pickle')
- original_obj = BasicDataclass(
- bool_attr=True,
- datetime_attr=datetime(2022, 2, 2),
- int_attr=2,
- str_attr='value',
- )
- cache['key_1'] = original_obj
-
- obj = cache['key_1']
- assert obj.bool_attr == original_obj.bool_attr
- assert obj.datetime_attr == original_obj.datetime_attr
- assert obj.int_attr == original_obj.int_attr
- assert obj.str_attr == original_obj.str_attr
+ cache = self.init_cache(serializer='pickle')
+ original_obj = BasicDataclass(
+ bool_attr=True,
+ datetime_attr=datetime(2022, 2, 2),
+ int_attr=2,
+ str_attr='value',
+ )
+ cache['key_1'] = original_obj
+
+ obj = cache['key_1']
+ assert obj.bool_attr == original_obj.bool_attr
+ assert obj.datetime_attr == original_obj.datetime_attr
+ assert obj.int_attr == original_obj.int_attr
+ assert obj.str_attr == original_obj.str_attr
def test_clear_and_work_again(self):
cache_1 = self.init_cache()
diff --git a/tests/integration/test_dynamodb.py b/tests/integration/test_dynamodb.py
index 84c1008..59f8ae1 100644
--- a/tests/integration/test_dynamodb.py
+++ b/tests/integration/test_dynamodb.py
@@ -5,7 +5,7 @@ from unittest.mock import patch
import pytest
from botocore.exceptions import ClientError
-from requests_cache.backends import DynamoDbCache, DynamoDbDict, DynamoDbDocumentDict
+from requests_cache.backends import DynamoDbCache, DynamoDbDict
from requests_cache.serializers import dynamodb_document_serializer
from tests.conftest import HTTPBIN_FORMATS, HTTPBIN_METHODS, fail_if_no_connection
from tests.integration.base_cache_test import TEST_SERIALIZERS, BaseCacheTest
@@ -86,12 +86,6 @@ class TestDynamoDbDict(BaseStorageTest):
assert ttl_value is None
-class TestDynamoDbDocumentDict(BaseStorageTest):
- storage_class = DynamoDbDocumentDict
- init_kwargs = DYNAMODB_OPTIONS
- picklable = True
-
-
class TestDynamoDbCache(BaseCacheTest):
backend_class = DynamoDbCache
init_kwargs = DYNAMODB_OPTIONS
diff --git a/tests/integration/test_mongodb.py b/tests/integration/test_mongodb.py
index 262ddd6..5ff6ae9 100644
--- a/tests/integration/test_mongodb.py
+++ b/tests/integration/test_mongodb.py
@@ -6,14 +6,8 @@ import pytest
from gridfs import GridFS
from gridfs.errors import CorruptGridFile, FileExists
-from requests_cache.backends import (
- GridFSCache,
- GridFSPickleDict,
- MongoCache,
- MongoDict,
- MongoDocumentDict,
-)
-from requests_cache.policy.expiration import NEVER_EXPIRE
+from requests_cache.backends import GridFSCache, GridFSDict, MongoCache, MongoDict
+from requests_cache.policy import NEVER_EXPIRE
from requests_cache.serializers import bson_document_serializer
from tests.conftest import HTTPBIN_FORMATS, HTTPBIN_METHODS, fail_if_no_connection, httpbin
from tests.integration.base_cache_test import TEST_SERIALIZERS, BaseCacheTest
@@ -37,11 +31,6 @@ def ensure_connection():
class TestMongoDict(BaseStorageTest):
storage_class = MongoDict
-
-class TestMongoPickleDict(BaseStorageTest):
- storage_class = MongoDocumentDict
- picklable = True
-
def test_connection_kwargs(self):
"""A spot check to make sure optional connection kwargs gets passed to connection"""
# MongoClient prevents direct access to private members like __init_kwargs;
@@ -60,7 +49,6 @@ class TestMongoPickleDict(BaseStorageTest):
class TestMongoCache(BaseCacheTest):
backend_class = MongoCache
-
init_kwargs = {'serializer': None} # Use class default serializer instead of pickle
@pytest.mark.parametrize('serializer', MONGODB_SERIALIZERS)
@@ -113,14 +101,14 @@ class TestMongoCache(BaseCacheTest):
assert session.cache.get_ttl() is None
-class TestGridFSPickleDict(BaseStorageTest):
- storage_class = GridFSPickleDict
+class TestGridFSDict(BaseStorageTest):
+ storage_class = GridFSDict
picklable = True
num_instances = 1 # Only test a single collecton instead of multiple
def test_connection_kwargs(self):
"""A spot check to make sure optional connection kwargs gets passed to connection"""
- cache = GridFSPickleDict(
+ cache = GridFSDict(
'test',
host='mongodb://0.0.0.0',
port=2222,
diff --git a/tests/integration/test_sqlite.py b/tests/integration/test_sqlite.py
index 84b399a..b696236 100644
--- a/tests/integration/test_sqlite.py
+++ b/tests/integration/test_sqlite.py
@@ -9,13 +9,14 @@ import pytest
from platformdirs import user_cache_dir
from requests_cache.backends.base import BaseCache
-from requests_cache.backends.sqlite import MEMORY_URI, SQLiteCache, SQLiteDict, SQLitePickleDict
+from requests_cache.backends.sqlite import MEMORY_URI, SQLiteCache, SQLiteDict
from requests_cache.models.response import CachedResponse
from tests.integration.base_cache_test import BaseCacheTest
from tests.integration.base_storage_test import CACHE_NAME, BaseStorageTest
-class SQLiteTestCase(BaseStorageTest):
+class TestSQLiteDict(BaseStorageTest):
+ storage_class = SQLiteDict
init_kwargs = {'use_temp': True}
@classmethod
@@ -178,15 +179,6 @@ class SQLiteTestCase(BaseStorageTest):
with pytest.raises(ValueError):
list(cache.sorted(key='invalid_key'))
-
-class TestSQLiteDict(SQLiteTestCase):
- storage_class = SQLiteDict
-
-
-class TestSQLitePickleDict(SQLiteTestCase):
- storage_class = SQLitePickleDict
- picklable = True
-
@pytest.mark.parametrize('limit', [None, 50])
def test_sorted__by_expires(self, limit):
cache = self.init_cache()
@@ -213,7 +205,7 @@ class TestSQLitePickleDict(SQLiteTestCase):
for i in range(100):
delta = 101 - i
if i % 2 == 1:
- delta -= 100
+ delta -= 101
response = CachedResponse(status_code=i, expires=now + timedelta(seconds=delta))
cache[f'key_{i}'] = response
@@ -227,6 +219,13 @@ class TestSQLitePickleDict(SQLiteTestCase):
assert prev_item is None or prev_item.expires < item.expires
assert item.status_code % 2 == 0
+ def test_filesize(self):
+ """Test approximate expected size of database file, in bytes"""
+ cache = self.init_cache()
+ for i in range(100):
+ cache[f'key_{i}'] = f'value_{i}'
+ assert 50000 < cache.filesize() < 200000
+
class TestSQLiteCache(BaseCacheTest):
backend_class = SQLiteCache
diff --git a/tests/unit/test_base_cache.py b/tests/unit/test_base_cache.py
index 0b87411..a39b238 100644
--- a/tests/unit/test_base_cache.py
+++ b/tests/unit/test_base_cache.py
@@ -5,7 +5,7 @@ from unittest.mock import patch
import pytest
from requests_cache import CachedResponse
-from requests_cache.backends import BaseCache, SQLitePickleDict
+from requests_cache.backends import BaseCache, SQLiteDict
from tests.conftest import MOCKED_URL, MOCKED_URL_HTTPS, MOCKED_URL_JSON, MOCKED_URL_REDIRECT
YESTERDAY = datetime.utcnow() - timedelta(days=1)
@@ -24,7 +24,7 @@ class TimeBomb:
def test_urls__with_invalid_response(mock_session):
responses = [mock_session.get(url) for url in [MOCKED_URL, MOCKED_URL_JSON, MOCKED_URL_HTTPS]]
responses[2] = AttributeError
- with patch.object(SQLitePickleDict, '__getitem__', side_effect=responses):
+ with patch.object(SQLiteDict, '__getitem__', side_effect=responses):
expected_urls = [MOCKED_URL, MOCKED_URL_JSON]
assert set(mock_session.cache.urls) == set(expected_urls)
@@ -67,7 +67,7 @@ def test_values__with_invalid_responses(check_expiry, expected_count, mock_sessi
responses[1] = AttributeError
responses[2] = CachedResponse(expires=YESTERDAY, url='test')
- with patch.object(SQLitePickleDict, '__getitem__', side_effect=responses):
+ with patch.object(SQLiteDict, '__getitem__', side_effect=responses):
values = mock_session.cache.values(check_expiry=check_expiry)
assert len(list(values)) == expected_count
diff --git a/tests/unit/test_session.py b/tests/unit/test_session.py
index e64a457..12411eb 100644
--- a/tests/unit/test_session.py
+++ b/tests/unit/test_session.py
@@ -3,6 +3,7 @@ import json
import time
from collections import UserDict, defaultdict
from datetime import datetime, timedelta
+from logging import getLogger
from pathlib import Path
from pickle import PickleError
from unittest.mock import patch
@@ -15,7 +16,7 @@ from requests.structures import CaseInsensitiveDict
from requests_cache import ALL_METHODS, CachedSession
from requests_cache._utils import get_placeholder_class
-from requests_cache.backends import BACKEND_CLASSES, BaseCache, SQLiteDict, SQLitePickleDict
+from requests_cache.backends import BACKEND_CLASSES, BaseCache, SQLiteDict
from requests_cache.backends.base import DESERIALIZE_ERRORS
from requests_cache.policy.expiration import DO_NOT_CACHE, EXPIRE_IMMEDIATELY, NEVER_EXPIRE
from tests.conftest import (
@@ -32,6 +33,7 @@ from tests.conftest import (
# Some tests must disable url normalization to retain the custom `http+mock//` protocol
patch_normalize_url = patch('requests_cache.cache_keys.normalize_url', side_effect=lambda x, y: x)
+logger = getLogger(__name__)
# Basic initialization
# -----------------------------------------------------
@@ -421,7 +423,7 @@ def test_unpickle_errors(mock_session):
"""If there is an error during deserialization, the request should be made again"""
assert mock_session.get(MOCKED_URL_JSON).from_cache is False
- with patch.object(SQLitePickleDict, '__getitem__', side_effect=PickleError):
+ with patch.object(SQLiteDict, '__getitem__', side_effect=PickleError):
resp = mock_session.get(MOCKED_URL_JSON)
assert resp.from_cache is False
assert resp.json()['message'] == 'mock json response'
@@ -649,7 +651,7 @@ def test_remove_expired_responses__error(mock_session):
raise PickleError
return response_1
- with patch.object(SQLitePickleDict, '__getitem__', side_effect=error_on_key):
+ with patch.object(SQLiteDict, '__getitem__', side_effect=error_on_key):
BaseCache.remove_expired_responses(mock_session.cache)
assert len(mock_session.cache.responses) == 1
assert mock_session.get(MOCKED_URL).from_cache is True
@@ -695,7 +697,7 @@ def test_remove_expired_responses__per_request(mock_session):
# All 3 responses should still be cached
mock_session.remove_expired_responses()
for response in mock_session.cache.responses.values():
- print('Expires:', response.expires - datetime.utcnow() if response.expires else None)
+ logger.info(f'Expires in {response.ttl} seconds')
assert len(mock_session.cache.responses) == 3
# One should be expired after 1s, and another should be expired after 2s