diff options
author | Jordan Cook <jordan.cook@pioneer.com> | 2022-03-19 16:49:27 -0500 |
---|---|---|
committer | Jordan Cook <jordan.cook@pioneer.com> | 2022-03-29 12:17:43 -0500 |
commit | 2578cde2692714f1d74fcc20b47fd68d81295b51 (patch) | |
tree | ca2b41d3c171394eac0cf2ea009d19182193c9ce /tests | |
parent | b3646b03bc05f5b05f4384eb9a2b4796fa59cb34 (diff) | |
download | requests-cache-2578cde2692714f1d74fcc20b47fd68d81295b51.tar.gz |
Fix some regression bugs and broken tests
Diffstat (limited to 'tests')
-rw-r--r-- | tests/conftest.py | 16 | ||||
-rw-r--r-- | tests/integration/base_cache_test.py | 2 | ||||
-rw-r--r-- | tests/unit/test_cache_control.py | 20 | ||||
-rw-r--r-- | tests/unit/test_session.py | 72 |
4 files changed, 63 insertions, 47 deletions
diff --git a/tests/conftest.py b/tests/conftest.py index aa2cb33..a21b3fc 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -13,6 +13,7 @@ from datetime import datetime, timedelta from functools import wraps from logging import basicConfig, getLogger from os.path import abspath, dirname, join +from unittest.mock import MagicMock from uuid import uuid4 import pytest @@ -213,6 +214,21 @@ def get_mock_adapter() -> Adapter: return adapter +def get_mock_response( + method='GET', + url='https://img.site.com/base/img.jpg', + status_code=200, + headers={}, + request_headers={}, +): + return MagicMock( + url=url, + status_code=status_code, + headers=headers, + request=MagicMock(method=method, url=url, headers=request_headers), + ) + + def fail_if_no_connection(connect_timeout: float = 1.0) -> bool: """Decorator for testing a backend connection. This will intentionally cause a test failure if the wrapped function doesn't have dependencies installed, doesn't connect after a short timeout, diff --git a/tests/integration/base_cache_test.py b/tests/integration/base_cache_test.py index 1fe4253..e0a2d06 100644 --- a/tests/integration/base_cache_test.py +++ b/tests/integration/base_cache_test.py @@ -359,7 +359,7 @@ class BaseCacheTest: session_factory = partial(self.init_session, clear=False) request_func = partial(_send_request, session_factory, url) - with ProcessPoolExecutor(max_workers=N_WORKERS) as executor: + with executor_class(max_workers=N_WORKERS) as executor: _ = list(executor.map(request_func, range(N_REQUESTS_PER_ITERATION))) # Some logging for debug purposes diff --git a/tests/unit/test_cache_control.py b/tests/unit/test_cache_control.py index 1d9f417..ac9342a 100644 --- a/tests/unit/test_cache_control.py +++ b/tests/unit/test_cache_control.py @@ -6,7 +6,7 @@ from requests import PreparedRequest from requests_cache.cache_control import DO_NOT_CACHE, CacheActions from requests_cache.models import CachedResponse, CacheSettings, RequestSettings -from tests.conftest import ETAG, HTTPDATE_STR, LAST_MODIFIED +from tests.conftest import ETAG, HTTPDATE_STR, LAST_MODIFIED, get_mock_response IGNORED_DIRECTIVES = [ 'no-transform', @@ -47,7 +47,7 @@ def test_init( actions = CacheActions.from_request( cache_key='key', request=request, - settings=RequestSettings(settings, expire_after=request_expire_after), + settings=settings, ) assert actions.expire_after == expected_expiration @@ -135,13 +135,10 @@ def test_init_from_settings_and_headers( """Test behavior with both cache settings and request headers. The only variation in behavior with cache_control=True is that expire_after=0 should *not* cause the cache read to be skipped. """ - request = MagicMock( - url='https://img.site.com/base/img.jpg', - headers=headers, - ) - + request = get_mock_response(headers=headers) settings = CacheSettings(cache_control=cache_control, expire_after=expire_after) actions = CacheActions.from_request('key', request, RequestSettings(settings)) + assert actions.expire_after == expected_expiration assert actions.skip_read == expected_skip_read @@ -235,7 +232,7 @@ def test_update_from_response(headers, expected_expiration): actions = CacheActions.from_request( 'key', MagicMock(url=url), RequestSettings(cache_control=True) ) - actions.update_from_response(MagicMock(url=url, headers=headers)) + actions.update_from_response(get_mock_response(headers=headers)) if expected_expiration == DO_NOT_CACHE: assert not actions.expire_after # May be either 0 or None @@ -250,7 +247,7 @@ def test_update_from_response__ignored(): actions = CacheActions.from_request( 'key', MagicMock(url=url), RequestSettings(cache_control=False) ) - actions.update_from_response(MagicMock(url=url, headers={'Cache-Control': 'max-age=5'})) + actions.update_from_response(get_mock_response(headers={'Cache-Control': 'max-age=5'})) assert actions.expire_after is None @@ -262,11 +259,12 @@ def test_update_from_response__revalidate(mock_datetime, cache_headers, validato expiration """ url = 'https://img.site.com/base/img.jpg' - headers = {**cache_headers, **validator_headers} actions = CacheActions.from_request( 'key', MagicMock(url=url), RequestSettings(cache_control=True) ) - actions.update_from_response(MagicMock(url=url, headers=headers)) + response = get_mock_response(headers={**cache_headers, **validator_headers}) + actions.update_from_response(response) + assert actions.expires == mock_datetime.utcnow() assert actions.skip_write is False diff --git a/tests/unit/test_session.py b/tests/unit/test_session.py index 86d10cb..9fe1dac 100644 --- a/tests/unit/test_session.py +++ b/tests/unit/test_session.py @@ -52,8 +52,8 @@ def test_init_backend_instance__kwargs(): ) assert session.cache.cache_name == 'test_cache' - assert session.cache.settings.ignored_parameters == ['foo'] - assert session.cache.settings.match_headers is True + assert session.settings.ignored_parameters == ['foo'] + assert session.settings.match_headers is True def test_init_backend_class(): @@ -81,18 +81,20 @@ def test_init_missing_backend_dependency(): def test_repr(mock_session): """Test session and cache string representations""" - mock_session.expire_after = 11 + mock_session.settings.expire_after = 11 mock_session.cache.responses['key'] = 'value' mock_session.cache.redirects['key'] = 'value' mock_session.cache.redirects['key_2'] = 'value' - assert mock_session.cache.cache_name in repr(mock_session) and '11' in repr(mock_session) - assert '2 redirects' in str(mock_session.cache) and '1 responses' in str(mock_session.cache) + assert mock_session.cache.cache_name in repr(mock_session) + assert '11' in repr(mock_session) + assert '2 redirects' in str(mock_session.cache) + assert '1 responses' in str(mock_session.cache) def test_response_defaults(mock_session): """Both cached and new responses should always have the following attributes""" - mock_session.expire_after = datetime.utcnow() + timedelta(days=1) + mock_session.settings.expire_after = datetime.utcnow() + timedelta(days=1) response_1 = mock_session.get(MOCKED_URL) response_2 = mock_session.get(MOCKED_URL) response_3 = mock_session.get(MOCKED_URL) @@ -134,8 +136,8 @@ def test_all_methods__ignored_parameters__not_matched(field, method, mock_sessio """Test all relevant combinations of methods and data fields. Requests with different request params, data, or json should not be cached under different keys based on an ignored param. """ - mock_session.cache.settings.ignored_parameters = ['ignored'] - mock_session.cache.settings.match_headers = True + mock_session.settings.ignored_parameters = ['ignored'] + mock_session.settings.match_headers = True params_1 = {'ignored': 'value_1', 'not_ignored': 'value_1'} params_2 = {'ignored': 'value_2', 'not_ignored': 'value_1'} params_3 = {'ignored': 'value_2', 'not_ignored': 'value_2'} @@ -153,7 +155,7 @@ def test_all_methods__ignored_parameters__redacted(field, method, mock_session): """Test all relevant combinations of methods and data fields. Requests with ignored params should have those values redacted from the cached response. """ - mock_session.cache.settings.ignored_parameters = ['access_token'] + mock_session.settings.ignored_parameters = ['access_token'] params_1 = {'access_token': 'asdf', 'not_ignored': 'value_1'} mock_session.request(method, MOCKED_URL, **{field: params_1}) @@ -296,7 +298,7 @@ def test_normalize_params__url(mock_session): def test_match_headers(mock_session): """With match_headers, requests with different headers should have different cache keys""" - mock_session.cache.settings.match_headers = True + mock_session.settings.match_headers = True headers_list = [ {'Accept': 'application/json'}, {'Accept': 'text/xml'}, @@ -310,7 +312,7 @@ def test_match_headers(mock_session): def test_match_headers__normalize(mock_session): """With match_headers, the same headers (in any order) should have the same cache key""" - mock_session.cache.settings.match_headers = True + mock_session.settings.match_headers = True headers = {'Accept': 'application/json', 'Custom': 'abc'} reversed_headers = {'Custom': 'abc', 'Accept': 'application/json'} assert mock_session.get(MOCKED_URL, headers=headers).from_cache is False @@ -319,7 +321,7 @@ def test_match_headers__normalize(mock_session): def test_match_headers__list(mock_session): """match_headers can optionally be a list of specific headers to include""" - mock_session.cache.settings.match_headers = ['Accept'] + mock_session.settings.match_headers = ['Accept'] headers_1 = {'Accept': 'application/json', 'User-Agent': 'qutebrowser'} headers_2 = {'Accept': 'application/json', 'User-Agent': 'Firefox'} headers_3 = {'Accept': 'text/plain', 'User-Agent': 'qutebrowser'} @@ -333,7 +335,7 @@ def test_match_headers__list(mock_session): def test_include_get_headers(): """include_get_headers is aliased to match_headers for backwards-compatibility""" session = CachedSession(include_get_headers=True, backend='memory') - assert session.cache.settings.match_headers is True + assert session.settings.match_headers is True # Error handling @@ -351,8 +353,8 @@ def test_cache_error(exception_cls, mock_session): def test_expired_request_error(mock_session): """Without stale_if_error (default), if there is an error while re-fetching an expired response, the request should be re-raised and the expired item deleted""" - mock_session.cache.settings.stale_if_error = False - mock_session.cache.settings.expire_after = 1 + mock_session.settings.stale_if_error = False + mock_session.settings.expire_after = 1 mock_session.get(MOCKED_URL) time.sleep(1) @@ -364,8 +366,8 @@ def test_expired_request_error(mock_session): def test_stale_if_error__exception(mock_session): """With stale_if_error, expect to get old cache data if there is an exception during a request""" - mock_session.cache.settings.stale_if_error = True - mock_session.cache.settings.expire_after = 1 + mock_session.settings.stale_if_error = True + mock_session.settings.expire_after = 1 assert mock_session.get(MOCKED_URL).from_cache is False assert mock_session.get(MOCKED_URL).from_cache is True @@ -377,9 +379,9 @@ def test_stale_if_error__exception(mock_session): def test_stale_if_error__error_code(mock_session): """With stale_if_error, expect to get old cache data if a response has an error status code""" - mock_session.cache.settings.stale_if_error = True - mock_session.cache.settings.expire_after = 1 - mock_session.cache.settings.allowable_codes = (200, 404) + mock_session.settings.stale_if_error = True + mock_session.settings.expire_after = 1 + mock_session.settings.allowable_codes = (200, 404) assert mock_session.get(MOCKED_URL_404).from_cache is False @@ -391,7 +393,7 @@ def test_stale_if_error__error_code(mock_session): def test_old_data_on_error(): """stale_if_error is aliased to old_data_on_error for backwards-compatibility""" session = CachedSession(old_data_on_error=True, backend='memory') - assert session.cache.settings.stale_if_error is True + assert session.settings.stale_if_error is True def test_cache_disabled(mock_session): @@ -431,7 +433,7 @@ def test_unpickle_errors(mock_session): def test_filter_fn(mock_session): - mock_session.cache.settings.filter_fn = lambda r: r.request.url != MOCKED_URL_JSON + mock_session.settings.filter_fn = lambda r: r.request.url != MOCKED_URL_JSON mock_session.get(MOCKED_URL) mock_session.get(MOCKED_URL_JSON) @@ -442,7 +444,7 @@ def test_filter_fn(mock_session): def test_filter_fn__retroactive(mock_session): """filter_fn should also apply to previously cached responses""" mock_session.get(MOCKED_URL_JSON) - mock_session.cache.settings.filter_fn = lambda r: r.request.url != MOCKED_URL_JSON + mock_session.settings.filter_fn = lambda r: r.request.url != MOCKED_URL_JSON mock_session.get(MOCKED_URL_JSON) assert not mock_session.cache.has_url(MOCKED_URL_JSON) @@ -453,7 +455,7 @@ def test_key_fn(mock_session): """Create a key based on only the request URL (without params)""" return request.url.split('?')[0] - mock_session.cache.settings.key_fn = create_key + mock_session.settings.key_fn = create_key mock_session.get(MOCKED_URL) response = mock_session.get(MOCKED_URL, params={'k': 'v'}) assert response.from_cache is True @@ -477,13 +479,13 @@ def test_hooks(mock_session): def test_do_not_cache(mock_session): """expire_after=0 should bypass the cache on both read and write""" - # Bypass read + # Skip read mock_session.get(MOCKED_URL) assert mock_session.cache.has_url(MOCKED_URL) assert mock_session.get(MOCKED_URL, expire_after=0).from_cache is False - # Bypass write - mock_session.expire_after = 0 + # Skip write + mock_session.settings.expire_after = 0 mock_session.get(MOCKED_URL_JSON) assert not mock_session.cache.has_url(MOCKED_URL_JSON) @@ -506,7 +508,7 @@ def test_304_not_modified( ): url = f'{MOCKED_URL}/endpoint_2' if cache_expired: - mock_session.expire_after = datetime.now() - timedelta(1) + mock_session.settings.expire_after = datetime.now() - timedelta(1) if cache_hit: mock_session.mock_adapter.register_uri('GET', url, status_code=200) mock_session.get(url) @@ -518,7 +520,7 @@ def test_304_not_modified( def test_url_allowlist(mock_session): """If the default is 0, only URLs matching patterns in urls_expire_after should be cached""" - mock_session.urls_expire_after = { + mock_session.settings.urls_expire_after = { MOCKED_URL_JSON: 60, '*': 0, } @@ -533,7 +535,7 @@ def test_remove_expired_responses(mock_session): mock_session.mock_adapter.register_uri( 'GET', unexpired_url, status_code=200, text='mock response' ) - mock_session.expire_after = 1 + mock_session.settings.expire_after = 1 mock_session.get(MOCKED_URL) mock_session.get(MOCKED_URL_JSON) time.sleep(1) @@ -571,7 +573,7 @@ def test_remove_expired_responses__error(mock_session): def test_remove_expired_responses__extend_expiration(mock_session): # Start with an expired response - mock_session.expire_after = datetime.utcnow() - timedelta(seconds=0.01) + mock_session.settings.expire_after = datetime.utcnow() - timedelta(seconds=0.01) mock_session.get(MOCKED_URL) # Set expiration in the future @@ -583,7 +585,7 @@ def test_remove_expired_responses__extend_expiration(mock_session): def test_remove_expired_responses__shorten_expiration(mock_session): # Start with a non-expired response - mock_session.expire_after = datetime.utcnow() + timedelta(seconds=1) + mock_session.settings.expire_after = datetime.utcnow() + timedelta(seconds=1) mock_session.get(MOCKED_URL) # Set expiration in the past @@ -624,7 +626,7 @@ def test_remove_expired_responses__per_request(mock_session): def test_request_expire_after__enable_expiration(mock_session): """No per-session expiration is set, but then overridden for a single request""" - mock_session.expire_after = None + mock_session.settings.expire_after = None response = mock_session.get(MOCKED_URL, expire_after=1) assert response.from_cache is False assert mock_session.get(MOCKED_URL).from_cache is True @@ -636,7 +638,7 @@ def test_request_expire_after__enable_expiration(mock_session): def test_request_expire_after__disable_expiration(mock_session): """A per-session expiration is set, but then disabled for a single request""" - mock_session.expire_after = 60 + mock_session.settings.expire_after = 60 response = mock_session.get(MOCKED_URL, expire_after=-1) response = mock_session.get(MOCKED_URL, expire_after=-1) assert response.from_cache is True @@ -645,7 +647,7 @@ def test_request_expire_after__disable_expiration(mock_session): def test_request_expire_after__prepared_request(mock_session): """Pre-request expiration should also work for PreparedRequests with CachedSession.send()""" - mock_session.expire_after = None + mock_session.settings.expire_after = None request = Request(method='GET', url=MOCKED_URL, headers={}, data=None).prepare() response = mock_session.send(request, expire_after=1) assert response.from_cache is False |