Skip to content

Commit

Permalink
More unit tests for Billing APi routes.
Browse files Browse the repository at this point in the history
  • Loading branch information
milo-hyben committed Jan 31, 2024
1 parent d113639 commit d7a5bb4
Show file tree
Hide file tree
Showing 2 changed files with 167 additions and 97 deletions.
4 changes: 0 additions & 4 deletions db/python/layers/billing.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,17 +262,13 @@ async def get_cost_by_batch_id(
# First get all batches and the min/max day to use for the query
ar_guid = await ar_batch_lookup_table.get_ar_guid_by_batch_id(batch_id)

print('ar_guid', ar_guid)

# The get all batches for the ar_guid
(
start_day,
end_day,
batches,
) = await ar_batch_lookup_table.get_batches_by_ar_guid(ar_guid)

print('batches', batches)

if not batches:
return BillingHailBatchCostRecord(ar_guid=ar_guid, batch_ids=[], costs=[])

Expand Down
260 changes: 167 additions & 93 deletions test/test_api_billing.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,25 @@
from test.testbase import run_as_sync
from unittest.mock import patch

import api.routes.billing as billing
from api.routes import billing
from models.models import (
BillingColumn,
BillingCostBudgetRecord,
BillingHailBatchCostRecord,
BillingTotalCostQueryModel,
BillingTotalCostRecord,
)


class TestApiBilling(unittest.TestCase):
"""Test API Billing routes"""
"""
Test API Billing routes
Billing routes are only calling layer functions and returning data it received
This set of tests only checks if all routes code has been called
and if data returned is the same as data received from layer functions
It does not check all possible combination of parameters as
Billing Layer and BQ Tables should be testing those
"""

def test_is_billing_enabled(self):
"""
Expand All @@ -27,154 +41,214 @@ async def test_get_gcp_projects_no_billing(self):

@run_as_sync
@patch('api.routes.billing.is_billing_enabled')
@patch('db.python.layers.billing.BillingLayer.get_gcp_projects')
async def test_get_gcp_projects(
self, mock_get_gcp_projects, mock_is_billing_enabled
@patch('db.python.layers.billing.BillingLayer.get_cost_by_ar_guid')
async def test_get_cost_by_ar_guid(
self, mock_get_cost_by_ar_guid, mock_is_billing_enabled
):
"""
Test get_gcp_projects function
Test get_cost_by_ar_guid function
"""

mockup_records = ['PROJECT1', 'PROJECT2']

ar_guid = 'test_ar_guid'
mockup_record = BillingHailBatchCostRecord(
ar_guid=ar_guid, batch_ids=None, costs=None
)
mock_is_billing_enabled.return_value = True
mock_get_gcp_projects.return_value = mockup_records

records = await billing.get_gcp_projects(author=None)
self.assertEqual(mockup_records, records)
mock_get_cost_by_ar_guid.return_value = mockup_record
records = await billing.get_cost_by_ar_guid(ar_guid, author=None)
self.assertEqual(mockup_record, records)

@run_as_sync
@patch('api.routes.billing.is_billing_enabled')
@patch('db.python.layers.billing.BillingLayer.get_topics')
async def test_get_topics(self, mock_get_topics, mock_is_billing_enabled):
@patch('db.python.layers.billing.BillingLayer.get_cost_by_batch_id')
async def test_get_cost_by_batch_id(
self, mock_get_cost_by_batch_id, mock_is_billing_enabled
):
"""
Test get_topics function
Test get_cost_by_batch_id function
"""

mockup_records = ['TOPIC1', 'TOPIC2']

ar_guid = 'test_ar_guid'
batch_id = 'test_batch_id'
mockup_record = BillingHailBatchCostRecord(
ar_guid=ar_guid, batch_ids=[batch_id], costs=None
)
mock_is_billing_enabled.return_value = True
mock_get_topics.return_value = mockup_records
mock_get_cost_by_batch_id.return_value = mockup_record
records = await billing.get_cost_by_batch_id(batch_id, author=None)
self.assertEqual(mockup_record, records)

records = await billing.get_topics(author=None)
self.assertEqual(mockup_records, records)
@run_as_sync
@patch('api.routes.billing.is_billing_enabled')
@patch('db.python.layers.billing.BillingLayer.get_total_cost')
async def test_get_total_cost(self, mock_get_total_cost, mock_is_billing_enabled):
"""
Test get_total_cost function
"""
query = BillingTotalCostQueryModel(fields=[], start_date='', end_date='')
mockup_record = [{'cost': 123.45}, {'cost': 123}]
expected = [BillingTotalCostRecord.from_json(r) for r in mockup_record]
mock_is_billing_enabled.return_value = True
mock_get_total_cost.return_value = mockup_record
records = await billing.get_total_cost(query, author=None)
self.assertEqual(expected, records)

@run_as_sync
@patch('api.routes.billing.is_billing_enabled')
@patch('db.python.layers.billing.BillingLayer.get_cost_categories')
async def test_get_cost_categories(
self, mock_get_cost_categories, mock_is_billing_enabled
@patch('db.python.layers.billing.BillingLayer.get_running_cost')
async def test_get_running_cost(
self, mock_get_running_cost, mock_is_billing_enabled
):
"""
Test get_cost_categories function
Test get_running_cost function
"""

mockup_records = ['CAT1', 'CAT2']

mockup_record = [
BillingCostBudgetRecord.from_json(
{'field': 'TOPIC1', 'total_monthly': 999.99, 'details': []}
),
BillingCostBudgetRecord.from_json(
{'field': 'TOPIC2', 'total_monthly': 123, 'details': []}
),
]
mock_is_billing_enabled.return_value = True
mock_get_cost_categories.return_value = mockup_records
mock_get_running_cost.return_value = mockup_record
records = await billing.get_running_costs(
field=BillingColumn.TOPIC, invoice_month=None, source=None, author=None
)
self.assertEqual(mockup_record, records)

records = await billing.get_cost_categories(author=None)
@patch('api.routes.billing.is_billing_enabled')
async def call_api_function(
self, api_function, mock_layer_function, mock_is_billing_enabled=None
):
"""
Common wrapper for all API calls, to avoid code duplication
API function is called with author=None
get_author function will be tested separately
We only testing if routes are calling layer functions and
returning data it received
"""
mockup_records = ['RECORD1', 'RECORD2']
mock_is_billing_enabled.return_value = True
mock_layer_function.return_value = mockup_records
records = await api_function(author=None)
self.assertEqual(mockup_records, records)

@run_as_sync
@patch('api.routes.billing.is_billing_enabled')
@patch('db.python.layers.billing.BillingLayer.get_skus')
async def test_get_skus(self, mock_get_skus, mock_is_billing_enabled):
@patch('db.python.layers.billing.BillingLayer.get_gcp_projects')
async def test_get_gcp_projects(self, mock_get_gcp_projects):
"""
Test get_skus function
Test get_gcp_projects function
"""
await self.call_api_function(billing.get_gcp_projects, mock_get_gcp_projects)

mockup_records = ['SKU1', 'SKU2', 'SKU3']
@run_as_sync
@patch('db.python.layers.billing.BillingLayer.get_topics')
async def test_get_topics(self, mock_get_topics):
"""
Test get_topics function
"""
await self.call_api_function(billing.get_topics, mock_get_topics)

mock_is_billing_enabled.return_value = True
mock_get_skus.return_value = mockup_records
@run_as_sync
@patch('db.python.layers.billing.BillingLayer.get_cost_categories')
async def test_get_cost_categories(self, mock_get_cost_categories):
"""
Test get_cost_categories function
"""
await self.call_api_function(
billing.get_cost_categories, mock_get_cost_categories
)

records = await billing.get_skus(author=None)
self.assertEqual(mockup_records, records)
@run_as_sync
@patch('db.python.layers.billing.BillingLayer.get_skus')
async def test_get_skus(self, mock_get_skus):
"""
Test get_skus function
"""
await self.call_api_function(billing.get_skus, mock_get_skus)

@run_as_sync
@patch('api.routes.billing.is_billing_enabled')
@patch('db.python.layers.billing.BillingLayer.get_datasets')
async def test_get_datasets(self, mock_get_datasets, mock_is_billing_enabled):
async def test_get_datasets(self, mock_get_datasets):
"""
Test get_datasets function
"""

mockup_records = ['DS1', 'DS2', 'DS3']

mock_is_billing_enabled.return_value = True
mock_get_datasets.return_value = mockup_records

records = await billing.get_datasets(author=None)
self.assertEqual(mockup_records, records)
await self.call_api_function(billing.get_datasets, mock_get_datasets)

@run_as_sync
@patch('api.routes.billing.is_billing_enabled')
@patch('db.python.layers.billing.BillingLayer.get_sequencing_types')
async def test_get_sequencing_types(
self, mock_get_sequencing_types, mock_is_billing_enabled
):
async def test_get_sequencing_types(self, mock_get_sequencing_types):
"""
Test get_sequencing_types function
"""

mockup_records = ['SEQ1', 'SEQ2']

mock_is_billing_enabled.return_value = True
mock_get_sequencing_types.return_value = mockup_records

records = await billing.get_sequencing_types(author=None)
self.assertEqual(mockup_records, records)
await self.call_api_function(
billing.get_sequencing_types, mock_get_sequencing_types
)

@run_as_sync
@patch('api.routes.billing.is_billing_enabled')
@patch('db.python.layers.billing.BillingLayer.get_stages')
async def test_get_stages(self, mock_get_stages, mock_is_billing_enabled):
async def test_get_stages(self, mock_get_stages):
"""
Test get_stages function
"""

mockup_records = ['STAGE1', 'STAGE2']

mock_is_billing_enabled.return_value = True
mock_get_stages.return_value = mockup_records

records = await billing.get_stages(author=None)
self.assertEqual(mockup_records, records)
await self.call_api_function(billing.get_stages, mock_get_stages)

@run_as_sync
@patch('api.routes.billing.is_billing_enabled')
@patch('db.python.layers.billing.BillingLayer.get_sequencing_groups')
async def test_get_sequencing_groups(
self, mock_get_sequencing_groups, mock_is_billing_enabled
):
async def test_get_sequencing_groups(self, mock_get_sequencing_groups):
"""
Test get_sequencing_groups function
"""

mockup_records = ['SG1', 'SG2']

mock_is_billing_enabled.return_value = True
mock_get_sequencing_groups.return_value = mockup_records

records = await billing.get_sequencing_groups(author=None)
self.assertEqual(mockup_records, records)
await self.call_api_function(
billing.get_sequencing_groups, mock_get_sequencing_groups
)

@run_as_sync
@patch('api.routes.billing.is_billing_enabled')
@patch('db.python.layers.billing.BillingLayer.get_compute_categories')
async def test_get_compute_categories(
self, mock_get_compute_categories, mock_is_billing_enabled
):
async def test_get_compute_categories(self, mock_get_compute_categories):
"""
Test get_compute_categories function
"""
await self.call_api_function(
billing.get_compute_categories, mock_get_compute_categories
)

mockup_records = ['CAT1', 'CAT2']
@run_as_sync
@patch('db.python.layers.billing.BillingLayer.get_cromwell_sub_workflow_names')
async def test_get_cromwell_sub_workflow_names(
self, mock_get_cromwell_sub_workflow_names
):
"""
Test get_cromwell_sub_workflow_names function
"""
await self.call_api_function(
billing.get_cromwell_sub_workflow_names,
mock_get_cromwell_sub_workflow_names,
)

mock_is_billing_enabled.return_value = True
mock_get_compute_categories.return_value = mockup_records
@run_as_sync
@patch('db.python.layers.billing.BillingLayer.get_wdl_task_names')
async def test_get_wdl_task_names(self, mock_get_wdl_task_names):
"""
Test get_wdl_task_names function
"""
await self.call_api_function(
billing.get_wdl_task_names, mock_get_wdl_task_names
)

records = await billing.get_compute_categories(author=None)
self.assertEqual(mockup_records, records)
@run_as_sync
@patch('db.python.layers.billing.BillingLayer.get_invoice_months')
async def test_get_invoice_months(self, mock_get_invoice_months):
"""
Test get_invoice_months function
"""
await self.call_api_function(
billing.get_invoice_months, mock_get_invoice_months
)

@run_as_sync
@patch('db.python.layers.billing.BillingLayer.get_namespaces')
async def test_get_namespaces(self, mock_get_namespaces):
"""
Test get_namespaces function
"""
await self.call_api_function(billing.get_namespaces, mock_get_namespaces)

0 comments on commit d7a5bb4

Please sign in to comment.