示例#1
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())
示例#2
0
    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())
示例#3
0
    def test_negative_values(self, mock_enumerate_dates, mock_run_forecast, mock_format_result):
        """COST-1110: ensure that the forecast response does not include negative numbers."""
        mock_run_forecast.return_value = Mock(
            prediction=[1, 0, -1, -2, -3], confidence_lower=[2, 1, 0, -1, -2], confidence_upper=[3, 2, 1, 0, -1]
        )
        params = self.mocked_query_params("?", AWSCostForecastView)
        instance = AWSForecast(params)
        instance.predict()

        self.assertIsInstance(mock_format_result.call_args[0][0], dict)
        for key, val_dict in mock_format_result.call_args[0][0].items():
            for inner_key, inner_val in val_dict.items():
                if "cost" in inner_key:
                    self.assertGreaterEqual(inner_val[0]["total_cost"], 0)
                    self.assertGreaterEqual(inner_val[0]["confidence_min"], 0)
                    self.assertGreaterEqual(inner_val[0]["confidence_max"], 0)
示例#4
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.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)
示例#5
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)
示例#6
0
 def test_results_never_outside_curren_month(self):
     """Test that our results stop at the end of the current month."""
     dh = DateHelper()
     params = self.mocked_query_params("?", AWSCostForecastView)
     forecast = AWSForecast(params)
     forecast.forecast_days_required = 100
     results = forecast.predict()
     dates = [result.get("date") for result in results]
     self.assertNotIn(dh.next_month_start, dates)
     self.assertEqual(dh.this_month_end.date(), max(dates))
示例#7
0
    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)
示例#8
0
    def test_add_additional_data_points(self):
        """Test that we fill in data to the end of the month."""
        dh = DateHelper()
        params = self.mocked_query_params("?", AWSCostForecastView)
        last_day_of_data = dh.last_month_start + timedelta(days=10)
        with patch("forecast.forecast.Forecast.dh") as mock_dh:
            mock_dh.today = dh.this_month_start
            mock_dh.this_month_end = dh.this_month_end
            mock_dh.last_month_start = dh.last_month_start
            mock_dh.last_month_end = last_day_of_data
            forecast = AWSForecast(params)
            results = forecast.predict()

            self.assertEqual(len(results), dh.this_month_end.day)
            for i, result in enumerate(results):
                self.assertEqual(
                    result.get("date"),
                    dh.this_month_start.date() + timedelta(days=i))
                for val in result.get("values", []):
                    cost = val.get("cost", {}).get("total", {}).get("value")
                    self.assertNotEqual(cost, 0)
示例#9
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())