From 058f6592d8815a64544f6721a9984b89ea92522a Mon Sep 17 00:00:00 2001 From: Frederick Muriuki Muriithi Date: Sat, 19 Feb 2022 03:21:27 +0300 Subject: Test partial corrs endpoint with non-existing control traits Test that if the endpoint is queried and not a single one of the control traits exists in the database, then the endpoint will respond with a 404 (not-found) status code. Summary of changes: * gn3/computations/partial_correlations.py: Check whether any control trait is found. If none is found, return "not-found" message. * gn3/db/partial_correlations.py: Fix bug in Geno query. * tests/integration/test_partial_correlations.py: Add test for non-existing control traits. Rename function to make it clearer what it is testing for. Remove obsoleted comments. --- gn3/computations/partial_correlations.py | 11 ++++-- gn3/db/partial_correlations.py | 3 +- tests/integration/test_partial_correlations.py | 49 +++++++++++++++++++++++--- 3 files changed, 54 insertions(+), 9 deletions(-) diff --git a/gn3/computations/partial_correlations.py b/gn3/computations/partial_correlations.py index 16cbbdb..1cc969c 100644 --- a/gn3/computations/partial_correlations.py +++ b/gn3/computations/partial_correlations.py @@ -621,14 +621,19 @@ def partial_correlations_entry(# pylint: disable=[R0913, R0914, R0911] "status": "not-found", "message": f"Could not find primary trait {primary_trait['trait_fullname']}" } + cntrl_traits = tuple( + trait for trait in all_traits + if trait["trait_fullname"] != primary_trait_name) + if not any(trait["haveinfo"] for trait in cntrl_traits): + return { + "status": "not-found", + "message": "None of the requested control traits were found."} + group = primary_trait["db"]["group"] primary_trait_data = all_traits_data[primary_trait["trait_name"]] primary_samples, primary_values, _primary_variances = export_informative( primary_trait_data) - cntrl_traits = tuple( - trait for trait in all_traits - if trait["trait_fullname"] != primary_trait_name) cntrl_traits_data = tuple( data for trait_name, data in all_traits_data.items() if trait_name != primary_trait["trait_name"]) diff --git a/gn3/db/partial_correlations.py b/gn3/db/partial_correlations.py index caf8d35..0931f09 100644 --- a/gn3/db/partial_correlations.py +++ b/gn3/db/partial_correlations.py @@ -197,13 +197,14 @@ def geno_traits_data(conn, traits): "AND GenoXRef.DataId = GenoData.Id " "AND GenoData.StrainId = Strain.Id " "ORDER BY Strain.Name").format( - species_ids=sp_ids, + species_ids=", ".join(["%s"] * len(sp_ids)), trait_names=", ".join(["%s"] * len(traits)), dataset_names=", ".join(["%s"] * len(dataset_names))) if len(sp_ids) > 0 and len(dataset_names) > 0: with conn.cursor(cursorclass=DictCursor) as cursor: cursor.execute( query, + sp_ids + tuple(trait["trait_name"] for trait in traits) + tuple(dataset_names)) return organise_trait_data_by_trait(cursor.fetchall()) diff --git a/tests/integration/test_partial_correlations.py b/tests/integration/test_partial_correlations.py index 17ea539..ff6d771 100644 --- a/tests/integration/test_partial_correlations.py +++ b/tests/integration/test_partial_correlations.py @@ -92,7 +92,6 @@ def test_partial_correlation_api_with_missing_request_data(client, post_data): response.status_code == 400 and response.is_json and response.json.get("status") == "error") - @pytest.mark.integration_test @pytest.mark.slow @pytest.mark.parametrize( @@ -118,9 +117,7 @@ def test_partial_correlation_api_with_missing_request_data(client, post_data): {"dataset": "a_dataset2", "name": "a_name2"}], "method": "a_method", "target_db": "a_db" - }, {# Temp -- Fails due to missing table. Remove this sample if it is - # confirmed that the deletion of the database table is on purpose, and - # that Temp traits are no longer a thing + }, {# Temp "primary_trait": {"dataset": "a_Temp_dataset", "name": "a_name"}, "control_traits": [ {"dataset": "a_dataset", "name": "a_name"}, @@ -128,7 +125,7 @@ def test_partial_correlation_api_with_missing_request_data(client, post_data): "method": "a_method", "target_db": "a_db" })) -def test_partial_correlation_api_with_non_existent_traits(client, post_data): +def test_partial_correlation_api_with_non_existent_primary_traits(client, post_data): """ Check that the system responds appropriately in the case where the user makes a request with a non-existent primary trait. @@ -137,3 +134,45 @@ def test_partial_correlation_api_with_non_existent_traits(client, post_data): assert ( response.status_code == 404 and response.is_json and response.json.get("status") != "error") + +@pytest.mark.integration_test +@pytest.mark.slow +@pytest.mark.parametrize( + "post_data", + ({# ProbeSet + "primary_trait": { + "dataset": "UCLA_BXDBXH_CARTILAGE_V2", "name": "ILM103710672"}, + "control_traits": [ + {"dataset": "a_dataset", "name": "a_name"}, + {"dataset": "a_dataset2", "name": "a_name2"}], + "method": "a_method", + "target_db": "a_db" + }, {# Publish + "primary_trait": {"dataset": "BXDPublish", "name": "BXD_12557"}, + "control_traits": [ + {"dataset": "a_dataset", "name": "a_name"}, + {"dataset": "a_dataset2", "name": "a_name2"}], + "method": "a_method", + "target_db": "a_db" + }, {# Geno + "primary_trait": {"dataset": "AKXDGeno", "name": "D4Mit16"}, + "control_traits": [ + {"dataset": "a_dataset", "name": "a_name"}, + {"dataset": "a_dataset2", "name": "a_name2"}], + "method": "a_method", + "target_db": "a_db" + } + # Temp -- the data in the database for these is ephemeral, making it + # difficult to test for this + )) +def test_partial_correlation_api_with_non_existent_control_traits(client, post_data): + """ + Check that the system responds appropriately in the case where the user + makes a request with a non-existent control traits. + + The code repetition here is on purpose - valuing clarity over succinctness. + """ + response = client.post("/api/correlation/partial", json=post_data) + assert ( + response.status_code == 404 and response.is_json and + response.json.get("status") != "error") -- cgit v1.2.3