From ba1e405b87c8679c4ad8f0fda463fc256dab93eb Mon Sep 17 00:00:00 2001 From: Mark Davenport Date: Sun, 2 Jun 2024 11:58:54 -0500 Subject: [PATCH] Fix tests --- cached_retry_session.py | 18 ++++++++++++++++++ crypto.py | 33 ++++++++++++--------------------- tests/crypto_test.py | 26 +++++++++++++++++++++----- 3 files changed, 51 insertions(+), 26 deletions(-) create mode 100644 cached_retry_session.py diff --git a/cached_retry_session.py b/cached_retry_session.py new file mode 100644 index 0000000..e1a1cac --- /dev/null +++ b/cached_retry_session.py @@ -0,0 +1,18 @@ +from requests.adapters import HTTPAdapter +from requests.packages.urllib3.util.retry import Retry +from requests_cache import CachedSession + + +class CachedRetrySession: + def __init__(self, cache_name, expire_after, total_retries, backoff_factor): + self.retry_strategy = Retry( + total=total_retries, + backoff_factor=backoff_factor, + ) + self.adapter = HTTPAdapter(max_retries=self.retry_strategy) + self.http = CachedSession(cache_name, expire_after=expire_after) + self.http.mount("https://", self.adapter) + self.http.mount("http://", self.adapter) + + def get_session(self): + return self.http diff --git a/crypto.py b/crypto.py index 3b9b948..61ca74b 100644 --- a/crypto.py +++ b/crypto.py @@ -1,16 +1,5 @@ import os -from requests.adapters import HTTPAdapter -from requests.packages.urllib3.util.retry import Retry -from requests_cache import CachedSession - -retry_strategy = Retry( - total=3, - backoff_factor=1, -) -adapter = HTTPAdapter(max_retries=retry_strategy) -http = CachedSession("crypto_cache", expire_after=60) -http.mount("https://", adapter) -http.mount("http://", adapter) +from cached_retry_session import CachedRetrySession TICKER_API_URL = "https://api.coingecko.com/api/v3" IMAGE_LOCATION = os.path.dirname(os.path.abspath(__file__)) + '/images/logos/' @@ -18,7 +7,8 @@ class Crypto: def __init__(self): - self.coins = Crypto.coins_request() + self.http = CachedRetrySession("crypto_cache", 60, 3, 1).get_session() + self.coins = self.coins_request() def get_coin(self, id): for coin in self.coins: @@ -49,32 +39,33 @@ def get_latest_price(self, ids, currency): e.g. BITCOIN: $35,000 DOGECOIN: $0.2500 """ prices = '' - response = Crypto.price_request(ids, currency) + response = self.price_request(ids, currency) for id in ids: price = "${:,}".format(float(response[id][currency])) price = price.rstrip('0').rstrip('.') coin = self.get_coin(id) + print(coin) prices += f'{str.upper(coin["symbol"])}:{price} ' return (prices) def get_details(self, id, currency): - response = Crypto.markets_request(id, currency) + response = self.markets_request(id, currency) price = "${:,}".format(float(response[0]['current_price'])) percent_change = "{0:.2f}%".format( float(response[0]['price_change_percentage_24h'])) return f'{price} {percent_change}%' - def price_request(ids, currency): - return http.get( + def price_request(self, ids, currency): + return self.http.get( f'{TICKER_API_URL}/simple/price/?ids=' + f'{",".join(ids)}&vs_currencies={currency}').json() - def markets_request(id, currency): - return http.get( + def markets_request(self, id, currency): + return self.http.get( f'{TICKER_API_URL}/coins/markets?vs_currency={currency}' + f'&ids={id}').json() - def coins_request(): - return http.get( + def coins_request(self): + return self.http.get( f'{TICKER_API_URL}/coins/list').json() diff --git a/tests/crypto_test.py b/tests/crypto_test.py index 3e790b5..69c7043 100644 --- a/tests/crypto_test.py +++ b/tests/crypto_test.py @@ -1,7 +1,8 @@ import responses - +import requests import os from unittest import TestCase +from unittest.mock import MagicMock, patch from crypto import Crypto from crypto import TICKER_API_URL @@ -17,10 +18,18 @@ def mock_details_response(current_price_value, return [{'current_price': current_price_value, 'price_change_percentage_24h': price_change_value}] +def mock_cacheless_session(): + mock_session = MagicMock() + mock_session.get_session.return_value = requests + return mock_session + class TestCrypto(TestCase): @responses.activate - def test_get_latest_price(self): + @patch('crypto.CachedRetrySession') + def test_get_latest_price(self, mock_http): + mock_http.return_value = mock_cacheless_session() + id = 'btc' currency = 'usd' responses.add(responses.GET, f'{TICKER_API_URL}/coins/list', @@ -48,14 +57,18 @@ def test_get_latest_price(self): [id], currency), 'DOGE:$0.223432 ') @responses.activate - def test_get_latest_price_error(self): + @patch('crypto.CachedRetrySession') + def test_get_latest_price_error(self, mock_http): + mock_http.return_value = mock_cacheless_session() responses.add(responses.GET, f'{TICKER_API_URL}/coins/list', json=[{'btc': {'symbol': 'BITCOIN'}}], status=200) c = Crypto() self.assertRaises(ConnectionError, c.get_latest_price, ['btc'], 'usd') @responses.activate - def test_get_coin(self): + @patch('crypto.CachedRetrySession') + def test_get_coin(self, mock_http): + mock_http.return_value = mock_cacheless_session() mock_coin = {'id': 'btc', 'name': 'bitcoin', 'symbol': 'btc'} responses.add(responses.GET, f'{TICKER_API_URL}/coins/list', json=[mock_coin], status=200) @@ -67,6 +80,7 @@ def test_get_coin(self): self.assertRaises(Exception, c.get_coin, 'shitcoin') + @responses.activate def test_get_logo(self): mock_coin = {'id': 'btc', 'name': 'bitcoin', 'symbol': 'btc'} location = os.path.abspath(os.path.join( @@ -85,7 +99,9 @@ def test_get_logo(self): self.assertEqual(logo, None) @responses.activate - def test_get_details(self): + @patch('crypto.CachedRetrySession') + def test_get_details(self, mock_http): + mock_http.return_value = mock_cacheless_session() id = 'btc' currency = 'usd' responses.add(responses.GET, f'{TICKER_API_URL}/coins/list',