Skip to content

Commit 41f0cd0

Browse files
authored
Merge pull request #72 from broadinstitute/sn_add_tests
Sn add tests
2 parents 3b2c417 + 4a04087 commit 41f0cd0

File tree

7 files changed

+283
-29
lines changed

7 files changed

+283
-29
lines changed

VERSION.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
11.3.1
2-
- Clean up float/int logic to be more concise
1+
11.3.2
2+
- Adding tests

ops_utils/request_util.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import backoff
55

66
from .token_util import Token
7-
from .vars import ARG_DEFAULTS
7+
from .vars import ARG_DEFAULTS, APPLICATION_JSON
88

99
GET = "GET"
1010
"""Method used for API GET endpoints"""
@@ -71,7 +71,7 @@ def run_request(
7171
files: Any = None,
7272
params: Optional[dict] = None,
7373
factor: int = 15,
74-
accept: Optional[str] = "application/json",
74+
accept: Optional[str] = APPLICATION_JSON,
7575
content_type: Optional[str] = None,
7676
accept_return_codes: list[int] = []
7777
) -> requests.Response:
@@ -149,7 +149,7 @@ def _make_request() -> requests.Response:
149149

150150
return _make_request()
151151

152-
def create_headers(self, content_type: Optional[str] = None, accept: Optional[str] = "application/json") -> dict:
152+
def create_headers(self, content_type: Optional[str] = None, accept: Optional[str] = APPLICATION_JSON) -> dict:
153153
"""
154154
Create headers for API calls.
155155

ops_utils/tdr_utils/tdr_api_utils.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from ..tdr_api_schema.create_dataset_schema import CreateDatasetSchema
1111
from ..tdr_api_schema.update_dataset_schema import UpdateSchema
1212
from .tdr_job_utils import MonitorTDRJob, SubmitAndMonitorMultipleJobs
13-
from ..vars import ARG_DEFAULTS, GCP
13+
from ..vars import ARG_DEFAULTS, GCP, APPLICATION_JSON
1414

1515

1616
class TDR:
@@ -204,7 +204,7 @@ def add_user_to_dataset(self, dataset_id: str, user: str, policy: str) -> reques
204204
uri=uri,
205205
method=POST,
206206
data=json.dumps(member_dict),
207-
content_type="application/json"
207+
content_type=APPLICATION_JSON
208208
)
209209

210210
def remove_user_from_dataset(self, dataset_id: str, user: str, policy: str) -> requests.Response:
@@ -253,7 +253,7 @@ def make_snapshot_public(self, snapshot_id: str) -> requests.Response:
253253
"""
254254
uri = f"{self.tdr_link}/snapshots/{snapshot_id}/public"
255255
logging.info(f"Making snapshot {snapshot_id} public")
256-
return self.request_util.run_request(uri=uri, method=PUT, content_type="application/json", data="true")
256+
return self.request_util.run_request(uri=uri, method=PUT, content_type=APPLICATION_JSON, data="true")
257257

258258
def get_snapshot_info(
259259
self,
@@ -505,7 +505,7 @@ def ingest_to_dataset(self, dataset_id: str, data: dict) -> requests.Response:
505505
return self.request_util.run_request(
506506
uri=uri,
507507
method=POST,
508-
content_type="application/json",
508+
content_type=APPLICATION_JSON,
509509
data=data
510510
)
511511

@@ -539,7 +539,7 @@ def file_ingest_to_dataset(
539539
response = self.request_util.run_request(
540540
uri=uri,
541541
method=POST,
542-
content_type="application/json",
542+
content_type=APPLICATION_JSON,
543543
data=json.dumps(data)
544544
)
545545
job_id = response.json()['id']
@@ -592,7 +592,7 @@ def _yield_dataset_metrics(self, dataset_id: str, target_table_name: str, query_
592592
response = self.request_util.run_request(
593593
uri=uri,
594594
method=POST,
595-
content_type="application/json",
595+
content_type=APPLICATION_JSON,
596596
data=json.dumps(search_request)
597597
)
598598
if not response or not response.json()["result"]:
@@ -709,7 +709,7 @@ def soft_delete_entries(
709709
method=POST,
710710
uri=uri,
711711
data=json.dumps(payload),
712-
content_type="application/json"
712+
content_type=APPLICATION_JSON
713713
)
714714
job_id = response.json()["id"]
715715
return MonitorTDRJob(tdr=self, job_id=job_id, check_interval=check_intervals, return_json=False).run()
@@ -851,7 +851,7 @@ def create_dataset( # type: ignore[return]
851851
method=POST,
852852
uri=uri,
853853
data=json.dumps(dataset_properties),
854-
content_type="application/json"
854+
content_type=APPLICATION_JSON
855855
)
856856
job_id = response.json()["id"]
857857
job_results = MonitorTDRJob(tdr=self, job_id=job_id, check_interval=30, return_json=True).run()
@@ -899,7 +899,7 @@ def update_dataset_schema( # type: ignore[return]
899899
response = self.request_util.run_request(
900900
uri=uri,
901901
method=POST,
902-
content_type="application/json",
902+
content_type=APPLICATION_JSON,
903903
data=json.dumps(request_body)
904904
)
905905
job_id = response.json()["id"]
@@ -1021,7 +1021,7 @@ def create_snapshot(
10211021
response = self.request_util.run_request(
10221022
uri=uri,
10231023
method=POST,
1024-
content_type="application/json",
1024+
content_type=APPLICATION_JSON,
10251025
data=json.dumps(payload)
10261026
)
10271027
job_id = response.json()["id"]

ops_utils/terra_util.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import os
1010

1111
from . import deprecated
12-
from .vars import GCP
12+
from .vars import GCP, APPLICATION_JSON
1313
from .gcp_utils import GCPCloudFunctions
1414
from .request_util import GET, POST, PATCH, PUT, DELETE, RunRequest
1515

@@ -266,7 +266,7 @@ def _yield_all_entity_metrics(self, entity: str, total_entities_per_page: int =
266266
response = self.request_util.run_request(
267267
uri=url,
268268
method=GET,
269-
content_type="application/json"
269+
content_type=APPLICATION_JSON
270270
)
271271
raw_text = response.text
272272
first_page_json = json.loads(
@@ -283,7 +283,7 @@ def _yield_all_entity_metrics(self, entity: str, total_entities_per_page: int =
283283
next_page = self.request_util.run_request(
284284
uri=url,
285285
method=GET,
286-
content_type="application/json",
286+
content_type=APPLICATION_JSON,
287287
params={"page": page}
288288
)
289289
raw_text = next_page.text
@@ -494,7 +494,7 @@ def update_user_acl(
494494
response = self.request_util.run_request(
495495
uri=url,
496496
method=PATCH,
497-
content_type="application/json",
497+
content_type=APPLICATION_JSON,
498498
data="[" + json.dumps(payload) + "]"
499499
)
500500

@@ -549,7 +549,7 @@ def update_multiple_users_acl(
549549
response = self.request_util.run_request(
550550
uri=url,
551551
method=PATCH,
552-
content_type="application/json",
552+
content_type=APPLICATION_JSON,
553553
data=json.dumps(acl_list)
554554
)
555555

@@ -592,7 +592,7 @@ def create_workspace(
592592
response = self.request_util.run_request(
593593
uri=f"{self.terra_link}/workspaces",
594594
method=POST,
595-
content_type="application/json",
595+
content_type=APPLICATION_JSON,
596596
data=json.dumps(payload),
597597
accept_return_codes=accept_return_codes
598598
)
@@ -681,7 +681,7 @@ def import_workflow(self, workflow_dict: dict, continue_if_exists: bool = False)
681681
uri=uri,
682682
method=POST,
683683
data=workflow_json,
684-
content_type="application/json",
684+
content_type=APPLICATION_JSON,
685685
accept_return_codes=accept_return_codes
686686
)
687687

@@ -711,7 +711,7 @@ def update_workspace_attributes(self, attributes: list[dict]) -> requests.Respon
711711
uri=f"{self.terra_link}/workspaces/{self.billing_project}/{self.workspace_name}/updateAttributes",
712712
method=PATCH,
713713
data=json.dumps(attributes),
714-
content_type="application/json"
714+
content_type=APPLICATION_JSON
715715
)
716716

717717
def leave_workspace(
@@ -768,7 +768,7 @@ def change_workspace_public_setting(self, public: bool) -> requests.Response:
768768
return self.request_util.run_request(
769769
uri=f"{RAWLS_LINK}/workspaces/v2/{self.billing_project}/{self.workspace_name}/settings",
770770
method=PUT,
771-
content_type="application/json",
771+
content_type=APPLICATION_JSON,
772772
data=json.dumps(body)
773773
)
774774

@@ -876,7 +876,7 @@ def add_user_comment_to_submission(self, submission_id: str, user_comment: str)
876876
return self.request_util.run_request(
877877
uri=f"{RAWLS_LINK}/workspaces/{self.billing_project}/{self.workspace_name}/submissions/{submission_id}",
878878
method=PATCH,
879-
content_type="application/json",
879+
content_type=APPLICATION_JSON,
880880
data=json.dumps({"userComment": user_comment}),
881881
)
882882

@@ -928,7 +928,7 @@ def initiate_submission(
928928
return self.request_util.run_request(
929929
uri=f"{self.terra_link}/workspaces/{self.billing_project}/{self.workspace_name}/submissions",
930930
method=POST,
931-
content_type="application/json",
931+
content_type=APPLICATION_JSON,
932932
data=json.dumps(payload),
933933
)
934934

@@ -950,7 +950,7 @@ def retry_failed_submission(self, submission_id: str) -> requests.Response:
950950
return self.request_util.run_request(
951951
uri=url,
952952
method=POST,
953-
content_type="application/json",
953+
content_type=APPLICATION_JSON,
954954
data=json.dumps(payload)
955955
)
956956

ops_utils/tests/test_tdr_table_utils.py

Lines changed: 152 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from unittest import TestCase
22
from unittest.mock import patch, MagicMock, call
33

4-
from ops_utils.tdr_utils.tdr_table_utils import SetUpTDRTables
4+
from ops_utils.tdr_utils.tdr_table_utils import SetUpTDRTables, MatchSchemas
55

66
TARGET_TABLE = "sample"
77
PRIMARY_KEY = f'{TARGET_TABLE}_id'
@@ -295,4 +295,154 @@ def test_compare_table_mis_matched_schemas(self):
295295
# Assertions
296296
self.assertEqual(
297297
columns_to_update, [{'name': 'participant', 'required': True, 'datatype': 'string', 'array_of': False, "action": "add"}]
298-
)
298+
)
299+
300+
301+
class TestMatchSchemas(TestCase):
302+
"""Tests for the MatchSchemas class"""
303+
304+
def setUp(self):
305+
# Create mock TDR instance
306+
self.mock_tdr = MagicMock()
307+
308+
# Define test data for original dataset
309+
self.orig_dataset_info = {
310+
"name": "original_dataset",
311+
"schema": {
312+
"tables": [
313+
{
314+
"name": "table_a",
315+
"columns": [
316+
{"name": "id", "datatype": "string", "mode": "required"},
317+
{"name": "value", "datatype": "string", "mode": "nullable"}
318+
]
319+
},
320+
{
321+
"name": "table_b",
322+
"columns": [
323+
{"name": "id", "datatype": "string", "mode": "required"},
324+
{"name": "count", "datatype": "integer", "mode": "nullable"}
325+
]
326+
}
327+
]
328+
}
329+
}
330+
331+
# Define test data for destination dataset
332+
self.dest_dataset_info = {
333+
"name": "destination_dataset",
334+
"schema": {
335+
"tables": [
336+
{
337+
"name": "table_a",
338+
"columns": [
339+
{"name": "id", "datatype": "string", "mode": "required"},
340+
{"name": "value", "datatype": "string", "mode": "nullable"}
341+
]
342+
}
343+
]
344+
}
345+
}
346+
347+
self.dest_dataset_id = "dest-dataset-123"
348+
349+
# Create MatchSchemas instance
350+
self.match_schemas = MatchSchemas(
351+
orig_dataset_info=self.orig_dataset_info,
352+
dest_dataset_info=self.dest_dataset_info,
353+
dest_dataset_id=self.dest_dataset_id,
354+
tdr=self.mock_tdr
355+
)
356+
357+
def test_init(self):
358+
"""Test initialization of MatchSchemas"""
359+
self.assertEqual(self.match_schemas.orig_dataset_info, self.orig_dataset_info)
360+
self.assertEqual(self.match_schemas.dest_dataset_info, self.dest_dataset_info)
361+
self.assertEqual(self.match_schemas.dest_dataset_id, self.dest_dataset_id)
362+
self.assertEqual(self.match_schemas.tdr, self.mock_tdr)
363+
364+
def test_run_adds_missing_tables(self):
365+
"""Test that the run method adds tables that exist in the original dataset but not in the destination"""
366+
# Run the matching process
367+
self.match_schemas.run()
368+
369+
# Verify that update_dataset_schema was called with the correct parameters
370+
self.mock_tdr.update_dataset_schema.assert_called_once()
371+
372+
# Get the arguments from the call
373+
args, kwargs = self.mock_tdr.update_dataset_schema.call_args
374+
375+
# Check dataset_id
376+
self.assertEqual(kwargs['dataset_id'], self.dest_dataset_id)
377+
378+
# Check that the tables_to_add contains table_b
379+
self.assertEqual(len(kwargs['tables_to_add']), 1)
380+
self.assertEqual(kwargs['tables_to_add'][0]['name'], 'table_b')
381+
382+
# Check that the update note is set
383+
self.assertTrue('update_note' in kwargs)
384+
385+
def test_run_no_missing_tables(self):
386+
"""Test that the run method doesn't update anything when all tables already exist"""
387+
# Modify destination dataset to include all tables from the original dataset
388+
self.dest_dataset_info = {
389+
"name": "destination_dataset",
390+
"schema": {
391+
"tables": [
392+
{
393+
"name": "table_a",
394+
"columns": [
395+
{"name": "id", "datatype": "string", "mode": "required"},
396+
{"name": "value", "datatype": "string", "mode": "nullable"}
397+
]
398+
},
399+
{
400+
"name": "table_b",
401+
"columns": [
402+
{"name": "id", "datatype": "string", "mode": "required"},
403+
{"name": "count", "datatype": "integer", "mode": "nullable"}
404+
]
405+
}
406+
]
407+
}
408+
}
409+
410+
# Create a new MatchSchemas instance with the updated destination dataset
411+
match_schemas = MatchSchemas(
412+
orig_dataset_info=self.orig_dataset_info,
413+
dest_dataset_info=self.dest_dataset_info,
414+
dest_dataset_id=self.dest_dataset_id,
415+
tdr=self.mock_tdr
416+
)
417+
418+
# Run the matching process
419+
match_schemas.run()
420+
421+
# Verify that update_dataset_schema was not called
422+
self.mock_tdr.update_dataset_schema.assert_not_called()
423+
424+
def test_run_multiple_missing_tables(self):
425+
"""Test that the run method adds multiple missing tables"""
426+
# Add another table to the original dataset
427+
self.orig_dataset_info["schema"]["tables"].append({
428+
"name": "table_c",
429+
"columns": [
430+
{"name": "id", "datatype": "string", "mode": "required"},
431+
{"name": "description", "datatype": "string", "mode": "nullable"}
432+
]
433+
})
434+
435+
# Run the matching process
436+
self.match_schemas.run()
437+
438+
# Verify that update_dataset_schema was called with the correct parameters
439+
self.mock_tdr.update_dataset_schema.assert_called_once()
440+
441+
# Get the arguments from the call
442+
args, kwargs = self.mock_tdr.update_dataset_schema.call_args
443+
444+
# Check that the tables_to_add contains both missing tables
445+
self.assertEqual(len(kwargs['tables_to_add']), 2)
446+
table_names = [table['name'] for table in kwargs['tables_to_add']]
447+
self.assertIn('table_b', table_names)
448+
self.assertIn('table_c', table_names)

0 commit comments

Comments
 (0)