def test_predict_response_date(self): """Test that predict() returns expected date range.""" dh = DateHelper() expected = [] for n in range(0, 10): expected.append({ "usage_start": dh.n_days_ago(dh.today, 10 - n).date(), "total_cost": 5, "infrastructure_cost": 3, "supplementary_cost": 2, }) mock_qset = MockQuerySet(expected) mocked_table = Mock() mocked_table.objects.filter.return_value.order_by.return_value.values.return_value.annotate.return_value = ( # noqa: E501 mock_qset) mocked_table.len = mock_qset.len params = self.mocked_query_params("?", AWSCostForecastView) instance = AWSForecast(params) instance.cost_summary_table = mocked_table results = instance.predict() for item in results: self.assertIsInstance(item.get("date"), date) self.assertLessEqual(item.get("date"), dh.this_month_end.date())
def test_predict_flat(self): """Test that predict() returns expected values for flat costs.""" dh = DateHelper() expected = [] for n in range(0, 10): expected.append({ "usage_start": (dh.this_month_start + timedelta(days=n)).date(), "total_cost": 5 + (0.01 * n), "infrastructure_cost": 3 + (0.01 * n), "supplementary_cost": 2 + (0.01 * n), }) mock_qset = MockQuerySet(expected) mocked_table = Mock() mocked_table.objects.filter.return_value.order_by.return_value.values.return_value.annotate.return_value = ( # noqa: E501 mock_qset) mocked_table.len = mock_qset.len params = self.mocked_query_params("?", AWSCostForecastView) instance = AWSForecast(params) instance.cost_summary_table = mocked_table results = instance.predict() for result in results: for val in result.get("values", []): with self.subTest(values=val): self.assertIsInstance(val.get("date"), date) for item, cost, delta in [ (val.get("cost"), 5, 1), (val.get("infrastructure"), 3, 1), (val.get("supplementary"), 2, 1), ]: with self.subTest(cost=cost, delta=delta, item=item): self.assertAlmostEqual(float( item.get("total").get("value")), cost, delta=delta) self.assertAlmostEqual(float( item.get("confidence_max").get("value")), cost, delta=delta) self.assertAlmostEqual(float( item.get("confidence_min").get("value")), cost, delta=delta) self.assertGreater( float(item.get("rsquared").get("value")), 0) for pval in item.get("pvalues").get("value"): self.assertGreaterEqual(float(pval), 0)
def test_predict_flat(self): """Test that predict() returns expected values for flat costs.""" dh = DateHelper() expected = [] for n in range(0, 10): expected.append({ "usage_start": dh.n_days_ago(dh.today, 10 - n).date(), "total_cost": 5, "infrastructure_cost": 3, "supplementary_cost": 2, }) mock_qset = MockQuerySet(expected) mocked_table = Mock() mocked_table.objects.filter.return_value.order_by.return_value.values.return_value.annotate.return_value = ( # noqa: E501 mock_qset) mocked_table.len = mock_qset.len params = self.mocked_query_params("?", AWSCostForecastView) instance = AWSForecast(params) instance.cost_summary_table = mocked_table results = instance.predict() for result in results: for val in result.get("values", []): self.assertIsInstance(val.get("date"), date) for item, cost in [ (val.get("cost"), 5), (val.get("infrastructure"), 3), (val.get("supplementary"), 2), ]: self.assertAlmostEqual(float( item.get("total").get("value")), cost, delta=0.0001) self.assertAlmostEqual(float( item.get("confidence_max").get("value")), cost, delta=0.0001) self.assertAlmostEqual(float( item.get("confidence_min").get("value")), cost, delta=0.0001) self.assertAlmostEqual(float( item.get("rsquared").get("value")), 1, delta=0.0001) self.assertGreaterEqual( float(item.get("pvalues").get("value")), 0)
def test_predict_few_values(self): """Test that predict() behaves well with a limited data set.""" dh = DateHelper() num_elements = [AWSForecast.MINIMUM - 1, AWSForecast.MINIMUM, AWSForecast.MINIMUM + 1] for number in num_elements: with self.subTest(num_elements=number): expected = [] for n in range(0, number): # the test data needs to include some jitter to avoid # division-by-zero in the underlying dot-product maths. expected.append( { "usage_start": dh.n_days_ago(dh.today, 10 - n).date(), "total_cost": 5 + (0.01 * n), "infrastructure_cost": 3 + (0.01 * n), "supplementary_cost": 2 + (0.01 * n), } ) mock_qset = MockQuerySet(expected) mocked_table = Mock() mocked_table.objects.filter.return_value.order_by.return_value.values.return_value.annotate.return_value = ( # noqa: E501 mock_qset ) mocked_table.len = mock_qset.len params = self.mocked_query_params("?", AWSCostForecastView) instance = AWSForecast(params) instance.cost_summary_table = mocked_table if number < AWSForecast.MINIMUM: # forecasting isn't useful with less than the minimum number of data points. with self.assertLogs(logger="forecast.forecast", level=logging.WARNING): results = instance.predict() self.assertEqual(results, []) else: results = instance.predict() self.assertNotEqual(results, []) for result in results: for val in result.get("values", []): self.assertIsInstance(val.get("date"), date) item = val.get("cost") self.assertGreaterEqual(float(item.get("total").get("value")), 0) self.assertGreaterEqual(float(item.get("confidence_max").get("value")), 0) self.assertGreaterEqual(float(item.get("confidence_min").get("value")), 0) self.assertGreaterEqual(float(item.get("rsquared").get("value")), 0) for pval in item.get("pvalues").get("value"): self.assertGreaterEqual(float(pval), 0) # test that the results always stop at the end of the month. self.assertEqual(results[-1].get("date"), dh.this_month_end.date())
def test_predict_increasing(self): """Test that predict() returns expected values for increasing costs.""" dh = DateHelper() expected = [] for n in range(0, 10): # the test data needs to include some jitter to avoid # division-by-zero in the underlying dot-product maths. expected.append({ "usage_start": dh.n_days_ago(dh.today, 10 - n).date(), "total_cost": 5 + random.random(), "infrastructure_cost": 3 + random.random(), "supplementary_cost": 2 + random.random(), }) mock_qset = MockQuerySet(expected) mocked_table = Mock() mocked_table.objects.filter.return_value.order_by.return_value.values.return_value.annotate.return_value = ( # noqa: E501 mock_qset) mocked_table.len = mock_qset.len params = self.mocked_query_params("?", AWSCostForecastView) instance = AWSForecast(params) instance.cost_summary_table = mocked_table results = instance.predict() for result in results: for val in result.get("values", []): self.assertIsInstance(val.get("date"), date) item = val.get("cost") self.assertGreaterEqual(float(item.get("total").get("value")), 0) self.assertGreaterEqual( float(item.get("confidence_max").get("value")), 0) self.assertGreaterEqual( float(item.get("confidence_min").get("value")), 0) self.assertGreaterEqual( float(item.get("rsquared").get("value")), 0) for pval in item.get("pvalues").get("value"): self.assertGreaterEqual(float(pval), 0)
def test_predict_few_values(self): """Test that predict() behaves well with a limited data set.""" dh = DateHelper() num_elements = [1, 2, 3, 4, 5] for number in num_elements: with self.subTest(num_elements=number): expected = [] for n in range(0, number): expected.append({ "usage_start": dh.n_days_ago(dh.today, 10 - n).date(), "total_cost": 5, "infrastructure_cost": 3, "supplementary_cost": 2, }) mock_qset = MockQuerySet(expected) mocked_table = Mock() mocked_table.objects.filter.return_value.order_by.return_value.values.return_value.annotate.return_value = ( # noqa: E501 mock_qset) mocked_table.len = mock_qset.len params = self.mocked_query_params("?", AWSCostForecastView) instance = AWSForecast(params) instance.cost_summary_table = mocked_table if number == 1: # forecasting isn't possible with only 1 data point. with self.assertLogs(logger="forecast.forecast", level=logging.WARNING): results = instance.predict() self.assertEqual(results, []) else: with self.assertLogs(logger="forecast.forecast", level=logging.WARNING): results = instance.predict() for result in results: for val in result.get("values", []): self.assertIsInstance(val.get("date"), date) item = val.get("cost") self.assertGreaterEqual( float(item.get("total").get("value")), 0) self.assertGreaterEqual( float( item.get("confidence_max").get( "value")), 0) self.assertGreaterEqual( float( item.get("confidence_min").get( "value")), 0) self.assertGreaterEqual( float(item.get("rsquared").get("value")), 0) self.assertGreaterEqual( float(item.get("pvalues").get("value")), 0) # test that the results always stop at the end of the month. self.assertEqual(results[-1].get("date"), dh.this_month_end.date())