diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e3a9d19 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.pyc +__pycache__/ +.mypy_cache/ diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..38f795a --- /dev/null +++ b/requirements.txt @@ -0,0 +1,19 @@ +appnope==0.1.0 +backcall==0.1.0 +decorator==4.4.0 +ipython==7.4.0 +ipython-genutils==0.2.0 +jedi==0.13.3 +nose==1.3.7 +parso==0.4.0 +pexpect==4.7.0 +pickleshare==0.7.5 +prompt-toolkit==2.0.9 +ptyprocess==0.6.0 +Pygments==2.3.1 +pymemcache==2.1.1 +redis==3.2.1 +six==1.12.0 +traitlets==4.3.2 +typed-ast==1.3.4 +wcwidth==0.1.7 diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..2e2c26f --- /dev/null +++ b/setup.py @@ -0,0 +1,8 @@ +from setuptools import setup + +setup( + name='testingtutorials', + version='0.1dev', + packages=['testingtutorials'], + license='' +) \ No newline at end of file diff --git a/testingtutorials/behaviortesting/__init__.py b/testingtutorials/behaviortesting/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/testingtutorials/behaviortesting/prices.py b/testingtutorials/behaviortesting/prices.py new file mode 100644 index 0000000..3455605 --- /dev/null +++ b/testingtutorials/behaviortesting/prices.py @@ -0,0 +1,68 @@ +import json +from abc import abstractmethod, ABC +from typing import List + +from pymemcache.client.base import Client +import redis + + +class Memcache: + def __init__(self): + self._client = Client(('localhost', 11211)) + + def prices(self) -> List[float]: + """ + Prices returns an array of all prices in the system. + + :return: + """ + # makes call to memcached... + return json.loads(self._client.get('prices')) + + +class Redis: + def __init__(self): + self._client = redis.StrictRedis() + + def prices(self) -> List[float]: + """ + Prices returns an array of all prices in the system. + + :return: + """ + # makes call to redis... + return self._client.lrange('prices', 0, -1) + + +class PriceAnalytics_Redis: + def __init__(self): + self.redis = Redis() + + def avg_price(self) -> float: + prices = self.redis.prices() + return sum(prices) / float(len(prices)) + + +class PriceAnalytics_MigrateMemcache: + def __init__(self): + self.memcache = Memcache() + + def avg_price(self) -> float: + prices = self.memcache.prices() + return sum(prices) / float(len(prices)) + + +class Datasource(ABC): + @abstractmethod + def prices(self) -> List[float]: + pass + + +class PriceAnalyticsEvolvable: + def __init__(self, datasource: Datasource): + self.datasource = datasource + + def avg_price(self) -> float: + prices = self.datasource.prices() + return sum(prices) / float(len(prices)) + diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/behaviortesting/__init__.py b/tests/behaviortesting/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/behaviortesting/test_prices.py b/tests/behaviortesting/test_prices.py new file mode 100644 index 0000000..1042cc8 --- /dev/null +++ b/tests/behaviortesting/test_prices.py @@ -0,0 +1,57 @@ +import unittest +from unittest.mock import patch, MagicMock +from testingtutorials.behaviortesting.prices import PriceAnalytics_Redis, PriceAnalyticsEvolvable, \ + PriceAnalytics_MigrateMemcache + + +class PriceAnalytics_Redis_TestCase(unittest.TestCase): + + @patch('testingtutorials.behaviortesting.prices.Redis') + def test_avg_price_success(self, mock_redis): + redis_instance = mock_redis.return_value + redis_instance.prices.return_value = [1, 1] + + analytics = PriceAnalytics_Redis() + + self.assertEqual( + 1, + analytics.avg_price(), + ) + + redis_instance.prices.assert_called_once() + + +class PriceAnalytics_MigrateMemcache_TestCase(unittest.TestCase): + + @patch('testingtutorials.behaviortesting.prices.Redis') + def test_avg_price_success(self, mock_redis): + redis_instance = mock_redis.return_value + redis_instance.prices.return_value = [1, 1] + + analytics = PriceAnalytics_MigrateMemcache() + + self.assertEqual( + 1, + analytics.avg_price(), + ) + + redis_instance.prices.assert_called_once() + + +class PriceAnalyticsEvolvableTestCase(unittest.TestCase): + + def test_avg_price_success(self): + ds = MagicMock( + prices=MagicMock( + return_value=[1, 1] + ) + ) + + analytics = PriceAnalyticsEvolvable( + datasource=ds + ) + + self.assertEqual( + 1, + analytics.avg_price(), + )