From 5b2ef4d597440943fc8fb2f290c77ca5318b156e Mon Sep 17 00:00:00 2001 From: Chiara Rasi Date: Mon, 13 Apr 2026 14:22:54 +0200 Subject: [PATCH 1/7] Refactor endpoint tests to use the same setup --- tests/server/test_server_responses.py | 318 +++++++++++++------------- 1 file changed, 154 insertions(+), 164 deletions(-) diff --git a/tests/server/test_server_responses.py b/tests/server/test_server_responses.py index 77f0063..d7ec32c 100644 --- a/tests/server/test_server_responses.py +++ b/tests/server/test_server_responses.py @@ -15,6 +15,17 @@ MATCH_EXTERNAL_ENDPOINT = "/match/external/" CONTENT_TYPE = "application/vnd.ga4gh.matchmaker.v1.0+json" +def _setup(mock_app, test_client, test_node, database): + # common setup used in all tests + ok_token = test_client["auth_token"] + + add_node(mongo_db=mock_app.db, obj=test_client, is_client=True) + add_node(mongo_db=mock_app.db, obj=test_node, is_client=False) + + assert database["matches"].find_one() is None + assert database["patients"].find_one() is None + + return ok_token def test_heartbeat(mock_app, database, test_client): """Test sending a GET request to see if app has a heartbeat""" @@ -53,56 +64,36 @@ def test_add_patient_no_auth(mock_app, gpx4_patients): assert response.status_code == 401 -def test_add_patient_malformed_patient(mock_app, test_client, gpx4_patients, test_node): +def test_add_patient_malformed_patient(mock_app, test_client, gpx4_patients, test_node, database): """Test sending a POST request to server to add a patient with malformed patient json""" - # Given a node with authorized token - ok_token = test_client["auth_token"] - - add_node(mongo_db=mock_app.db, obj=test_client, is_client=True) - add_node(mongo_db=mock_app.db, obj=test_node, is_client=False) # + ok_token = _setup(mock_app, test_client, test_node, database) - # send a malformed json object using a valid auth token malformed_json = "{'_id': 'patient_id' }" + response = mock_app.test_client().post( - ADD_PATIENT_ENDPOINT, data=malformed_json, headers=auth_headers(ok_token) + ADD_PATIENT_ENDPOINT, + data=malformed_json, + headers=auth_headers(ok_token), ) - # and check that you get the correct error code from server(400) + assert response.status_code == 400 -def test_add_patient_malformed_data(mock_app, test_client, gpx4_patients, test_node): +def test_add_patient_malformed_data(mock_app, test_client, gpx4_patients, test_node, database): """Test sending a POST request to server to add a patient with malformed data""" patient_data = gpx4_patients[1] - # Given a node with authorized token - ok_token = test_client["auth_token"] - - add_node(mongo_db=mock_app.db, obj=test_client, is_client=True) - add_node( - mongo_db=mock_app.db, obj=test_node, is_client=False - ) # add a test node, to perform external matching + ok_token = _setup(mock_app, test_client, test_node, database) - # add a patient not conforming to MME API using a valid auth token response = mock_app.test_client().post( - ADD_PATIENT_ENDPOINT, data=json.dumps(patient_data), headers=auth_headers(ok_token) + ADD_PATIENT_ENDPOINT, + data=json.dumps(patient_data), + headers=auth_headers(ok_token), ) - # and check that the server returns an error 422 (unprocessable entity) - assert response.status_code == 422 - - -def _setup(mock_app, test_client, test_node, database): - # common setup used in all tests - ok_token = test_client["auth_token"] - - add_node(mongo_db=mock_app.db, obj=test_client, is_client=True) - add_node(mongo_db=mock_app.db, obj=test_node, is_client=False) - - assert database["matches"].find_one() is None - assert database["patients"].find_one() is None - return ok_token + assert response.status_code == 422 @responses.activate @@ -214,329 +205,328 @@ def test_metrics(mock_app, database, test_client, demo_data_path, match_objs): def test_nodes_view(mock_app, database, test_node, test_client): """testing viewing the list of connected nodes as an authenticated client""" - # insert a test client in database - add_node(mongo_db=database, obj=test_client, is_client=True) - ok_token = test_client["auth_token"] + ok_token = _setup(mock_app, test_client, test_node, database) + + # Clear nodes added by _setup to preserve original test logic + database["nodes"].delete_many({}) - # If you try to see nodes without being authorized + # Unauthorized request response = mock_app.test_client().get("nodes") - # You should get a not authorized code from server assert response.status_code == 401 - # since there are no connected nodes in database + # No nodes in database assert database["nodes"].find_one() is None - # When you send an authorized request + + # Add only client (as in original test) + add_node(mongo_db=database, obj=test_client, is_client=True) + + # Authorized request → empty list response = mock_app.test_client().get("nodes", headers=auth_headers(ok_token)) data = json.loads(response.data) - # you shoud get an empty list assert data == [] - # insert a test node in database + # Add a test node add_node(mongo_db=database, obj=test_node, is_client=False) - # When you send an authorized request + + # Authorized request → one node response = mock_app.test_client().get("nodes", headers=auth_headers(ok_token)) data = json.loads(response.data) - # this time you should get a list with one element assert len(data) == 1 - # and the id of the element is the id of the node assert data[0]["id"] == test_node["_id"] -def test_delete_patient(mock_app, database, gpx4_patients, test_client, match_objs): +def test_delete_patient(mock_app, database, gpx4_patients, test_client, test_node, match_objs): """Test deleting a patient from database by sending a DELETE request""" - # load 2 patients from demo data in mock database + # GIVEN 2 patients already exist in DB assert len(gpx4_patients) == 2 - inserted_ids = [] + for pat in gpx4_patients: - # convert patient in mme patient type (convert also gene to ensembl) mme_pat = mme_patient(pat, True) - inserted_ids.append(backend_add_patient(database, mme_pat)) - - assert len(inserted_ids) == 2 + backend_add_patient(database, mme_pat) - # 50 cases present on patients collection delete_id = "P0001058" - # try to delete patient without auth token: - response = mock_app.test_client().delete("".join([DELETE_PATIENT_ENDPOINT, delete_id])) + # WHEN deleting without auth + response = mock_app.test_client().delete(DELETE_PATIENT_ENDPOINT + delete_id) assert response.status_code == 401 - # Add a valid client node + # GIVEN an authorized client node ok_token = test_client["auth_token"] add_node(mongo_db=mock_app.db, obj=test_client, is_client=True) - # Send delete request providing a valid token but a non valid id + # WHEN deleting with invalid patient ID response = mock_app.test_client().delete( - "".join([DELETE_PATIENT_ENDPOINT, "not_a_valid_ID"]), headers=auth_headers(ok_token) + DELETE_PATIENT_ENDPOINT + "not_a_valid_ID", + headers=auth_headers(ok_token), ) assert response.status_code == 200 + data = json.loads(response.data) - # but server returns error assert ( - data["message"] == "ERROR. Could not delete a patient with ID not_a_valid_ID from database" + data["message"] + == "ERROR. Could not delete a patient with ID not_a_valid_ID from database" ) - assert database["matches"].find_one() is None # no matches in database - # insert into database some mock matching objects + # ensure no matches initially + assert database["matches"].find_one() is None + + # insert mock matches database["matches"].insert_many(match_objs) - # patient "delete_id" should have two associated matches in database + # ensure correct match count before deletion results = database["matches"].find({"data.patient.id": delete_id}) assert len(list(results)) == 2 - # Send valid patient ID and valid token + # WHEN deleting valid patient response = mock_app.test_client().delete( - "".join([DELETE_PATIENT_ENDPOINT, delete_id]), headers=auth_headers(ok_token) + DELETE_PATIENT_ENDPOINT + delete_id, + headers=auth_headers(ok_token), ) assert response.status_code == 200 - # make sure that the patient was removed from database - results = database["patients"].find() - assert len(list(results)) == 1 + # THEN patient should be removed + assert len(list(database["patients"].find({}))) == 1 - # make sure that patient matches are also gone - results = database["matches"].find() - assert len(list(results)) == 1 + # AND related matches should be cleaned up + assert len(list(database["matches"].find({}))) == 1 -def test_patient_matches(mock_app, database, match_objs, test_client): +def test_patient_matches(mock_app, database, match_objs, test_client, test_node): """testing the endpoint that retrieves the matchings by patient ID""" - # Add a valid client node - ok_token = test_client["auth_token"] - add_node(mongo_db=mock_app.db, obj=test_client, is_client=True) + # Setup authorized client and node + ok_token = _setup(mock_app, test_client, test_node, database) # start from a database with no matches assert database["matches"].find_one() is None - # import mock matches into datababase + + # import mock matches into database database["matches"].insert_many(match_objs) - # database now should have two matching objects - # test endpoint to get matches by ID - # test by sending a non-authorized request + # unauthorized request response = mock_app.test_client().get("matches/P0001058") - # response gives a 401 code (not authorized) assert response.status_code == 401 - # try with an authorized request with a used ID that is not in database - response = mock_app.test_client().get("matches/unknown_patient", headers=auth_headers(ok_token)) - # response gives success + # authorized request with unknown patient + response = mock_app.test_client().get( + "matches/unknown_patient", + headers=auth_headers(ok_token), + ) assert response.status_code == 200 + data = json.loads(response.data) - # but the patient is not found by server assert ( - data["message"] == "Could not find any matches in database for patient ID unknown_patient" + data["message"] + == "Could not find any matches in database for patient ID unknown_patient" ) - # Try with authenticates request and valid patient - response = mock_app.test_client().get("matches/P0001058", headers=auth_headers(ok_token)) - # response gives success + # authorized request with valid patient + response = mock_app.test_client().get( + "matches/P0001058", + headers=auth_headers(ok_token), + ) assert response.status_code == 200 + data = json.loads(response.data) - # and there are matches in it - assert ( - len(data["matches"]) == 2 - ) # 2 matches returned because endpoint returns only matches with results + assert len(data["matches"]) == 2 # only matches with results returned - # Test that there are actually 3 matches by calling directly the function returning matches + # direct function: all matches matches = patient_matches( - database=database, patient_id="P0001058", type=None, with_results=False + database=database, + patient_id="P0001058", + type=None, + with_results=False, ) assert len(matches) == 3 + for match in matches: for result in match["results"]: for patient in result["patients"]: assert patient["patient"]["id"] - # Call the same function to get only external matches + # external matches only matches = patient_matches( - database=database, patient_id="P0001058", type="external", with_results=False + database=database, + patient_id="P0001058", + type="external", + with_results=False, ) assert len(matches) == 1 - # Call the same function to get only external matches + # internal matches only matches = patient_matches( - database=database, patient_id="P0001058", type="internal", with_results=False + database=database, + patient_id="P0001058", + type="internal", + with_results=False, ) assert len(matches) == 2 @responses.activate def test_match_hgnc_symbol_patient( - mock_app, gpx4_patients, test_client, database, mocked_ensemble_responses + mock_app, gpx4_patients, test_client, test_node, database, mocked_ensemble_responses ): """Testing matching patient with gene symbol against patientMatcher database (internal matching)""" - # add an authorized client to database - ok_token = test_client["auth_token"] - add_node(mongo_db=mock_app.db, obj=test_client, is_client=True) + # Setup authorized client and node + ok_token = _setup(mock_app, test_client, test_node, database) query_patient = {"patient": gpx4_patients[0]} assert query_patient["patient"]["genomicFeatures"][0]["gene"]["id"] == "GPX4" - # load 2 test patient in mock database + # Load 2 test patients into mock database assert len(gpx4_patients) == 2 inserted_ids = [] for pat in gpx4_patients: - # convert patient in mme patient type (convert also gene to ensembl) mme_pat = mme_patient(pat, True) inserted_ids.append(backend_add_patient(database, mme_pat)) - assert len(inserted_ids) == 2 - # test the API response validator with non valid patient data: + # Validate API response validator malformed_match_results = {"results": "fakey_results"} assert validate_response(malformed_match_results) == 422 - # make sure that there are no patient matches in the 'matches collection' + # Ensure no matches exist initially assert database["matches"].find_one() is None - # send a POST request to match patient with patients in database + # Send match request response = mock_app.test_client().post( - MATCH_ENDPOINT, data=json.dumps(query_patient), headers=auth_headers(ok_token) + MATCH_ENDPOINT, + data=json.dumps(query_patient), + headers=auth_headers(ok_token), ) - assert response.status_code == 200 # POST request should be successful + assert response.status_code == 200 + data = json.loads(response.data) - # data should contain results and the max number of results is as defined in the config file + assert isinstance(data["results"], list) assert len(data["results"]) == 2 - assert type(data["results"]) == list # which is a list - assert "patient" in data["results"][0] # of patients - assert "score" in data["results"][0] # with matching scores - assert "contact" in data["results"][0]["patient"] # contact info should be available as well + assert "patient" in data["results"][0] + assert "score" in data["results"][0] + assert "contact" in data["results"][0]["patient"] - # make sure that there are match object is created in db for this internal matching + # Verify DB match object match = database["matches"].find_one() for res in match["results"]: for pat in res["patients"]: - assert pat["patient"]["contact"] # each result should have a contact person + assert pat["patient"]["contact"] assert pat["score"]["patient"] > 0 @responses.activate def test_match_ensembl_patient( - mock_app, test_client, gpx4_patients, database, mocked_ensemble_responses + mock_app, test_client, gpx4_patients, test_node, database, mocked_ensemble_responses ): - """Test matching patient with ensembl gene against patientMatcher database (internal matching)""" + """Test matching patient with Ensembl gene against patientMatcher database (internal matching)""" - # add an authorized client to database - ok_token = test_client["auth_token"] - add_node(mongo_db=mock_app.db, obj=test_client, is_client=True) + # Setup authorized client + node + ok_token = _setup(mock_app, test_client, test_node, database) query_patient = {"patient": mme_patient(gpx4_patients[0], True)} assert query_patient["patient"]["genomicFeatures"][0]["gene"]["id"].startswith("ENSG") - # load 2 test patient in mock database assert len(gpx4_patients) == 2 inserted_ids = [] for pat in gpx4_patients: - # convert patient in mme patient type (convert also gene to ensembl) mme_pat = mme_patient(pat, True) inserted_ids.append(backend_add_patient(database, mme_pat)) - assert len(inserted_ids) == 2 - # make sure that there are no patient matches in the 'matches collection' assert database["matches"].find_one() is None - # send a POST request to match patient with patients in database response = mock_app.test_client().post( - MATCH_ENDPOINT, data=json.dumps(query_patient), headers=auth_headers(ok_token) + MATCH_ENDPOINT, + data=json.dumps(query_patient), + headers=auth_headers(ok_token), ) - assert response.status_code == 200 # POST request should be successful + assert response.status_code == 200 + data = json.loads(response.data) - # data should contain results and the max number of results is as defined in the config file + assert isinstance(data["results"], list) assert len(data["results"]) == 2 - assert type(data["results"]) == list # which is a list - assert "patient" in data["results"][0] # of patients - assert "score" in data["results"][0] # with matching scores - assert "contact" in data["results"][0]["patient"] # contact info should be available as well + assert "patient" in data["results"][0] + assert "score" in data["results"][0] + assert "contact" in data["results"][0]["patient"] - # make sure that a match object is created in db for this internal matching match = database["matches"].find_one() for res in match["results"]: for pat in res["patients"]: - assert pat["patient"]["contact"] # each result should have a contact person + assert pat["patient"]["contact"] assert pat["score"]["patient"] > 0 - # and query patient should have hgnc gene symbol saved as non-standard _geneName field + assert match["data"]["patient"]["genomicFeatures"][0]["gene"]["_geneName"] == "GPX4" @responses.activate -def test_match_entrez_patient(mock_app, test_client, gpx4_patients, database): - """Test matching patient with ensembl gene against patientMatcher database (internal matching)""" +def test_match_entrez_patient(mock_app, test_client, gpx4_patients, test_node, database): + """Test matching patient with Ensembl gene against patientMatcher database (internal matching)""" - # GIVEN a mocked Ensembl REST API converting gene symbol to Ensembl ID + # Mock Ensembl services responses.add( responses.GET, - f"https://grch37.rest.ensembl.org/xrefs/symbol/homo_sapiens/GPX4?external_db=HGNC", + "https://grch37.rest.ensembl.org/xrefs/symbol/homo_sapiens/GPX4?external_db=HGNC", json=[{"id": "ENSG00000167468", "type": "gene"}], status=200, ) - # GIVEN a mocked Ensembl gene lookup service: responses.add( responses.GET, - f"https://grch37.rest.ensembl.org/lookup/id/ENSG00000167468", + "https://grch37.rest.ensembl.org/lookup/id/ENSG00000167468", json=[{"display_name": "GPX4"}], status=200, ) - # GIVEN a mocked liftover service: responses.add( responses.GET, - f"https://grch37.rest.ensembl.org/map/human/GRCh37/19:1105813..1105814/GRCh38?content-type=application/json", + "https://grch37.rest.ensembl.org/map/human/GRCh37/19:1105813..1105814/GRCh38?content-type=application/json", json=[], status=200, ) + responses.add( responses.GET, - f"https://grch37.rest.ensembl.org/map/human/GRCh37/19:1106232..1106238/GRCh38?content-type=application/json", + "https://grch37.rest.ensembl.org/map/human/GRCh37/19:1106232..1106238/GRCh38?content-type=application/json", json=[], status=200, ) - # add an authorized client to database - ok_token = test_client["auth_token"] - add_node(mongo_db=mock_app.db, obj=test_client, is_client=True) + # Setup authorized client + node + ok_token = _setup(mock_app, test_client, test_node, database) query_patient = {"patient": gpx4_patients[0]} for feat in query_patient["patient"]["genomicFeatures"]: assert feat["gene"]["id"] == "GPX4" - # load 2 test patient in mock database assert len(gpx4_patients) == 2 inserted_ids = [] for pat in gpx4_patients: - # convert patient in mme patient type (convert also gene to ensembl) mme_pat = mme_patient(pat, True) inserted_ids.append(backend_add_patient(database, mme_pat)) - assert len(inserted_ids) == 2 - # make sure that there are no patient matches in the 'matches collection' assert database["matches"].find_one() is None - # send a POST request to match patient with patients in database response = mock_app.test_client().post( - MATCH_ENDPOINT, data=json.dumps(query_patient), headers=auth_headers(ok_token) + MATCH_ENDPOINT, + data=json.dumps(query_patient), + headers=auth_headers(ok_token), ) - assert response.status_code == 200 # POST request should be successful + assert response.status_code == 200 + data = json.loads(response.data) - # data should contain results and the max number of results is as defined in the config file + assert isinstance(data["results"], list) assert len(data["results"]) == 2 - assert type(data["results"]) == list # which is a list - assert "patient" in data["results"][0] # of patients - assert "score" in data["results"][0] # with matching scores - assert "contact" in data["results"][0]["patient"] # contact info should be available as well + assert "patient" in data["results"][0] + assert "score" in data["results"][0] + assert "contact" in data["results"][0]["patient"] - # make sure that a match object is created in db for this internal matching match = database["matches"].find_one() for res in match["results"]: for pat in res["patients"]: - assert pat["patient"]["contact"] # each result should have a contact person + assert pat["patient"]["contact"] assert pat["score"]["patient"] > 0 - # and query patient should have hgnc gene symbol saved as non-standard _geneName field + assert match["data"]["patient"]["genomicFeatures"][0]["gene"]["_geneName"] == "GPX4" From 81063e2b4e7ce18fc1673a324568a41b0ff98a76 Mon Sep 17 00:00:00 2001 From: Chiara Rasi Date: Mon, 13 Apr 2026 14:27:25 +0200 Subject: [PATCH 2/7] Black as in action --- tests/server/test_server_responses.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/server/test_server_responses.py b/tests/server/test_server_responses.py index d7ec32c..58859bb 100644 --- a/tests/server/test_server_responses.py +++ b/tests/server/test_server_responses.py @@ -15,6 +15,7 @@ MATCH_EXTERNAL_ENDPOINT = "/match/external/" CONTENT_TYPE = "application/vnd.ga4gh.matchmaker.v1.0+json" + def _setup(mock_app, test_client, test_node, database): # common setup used in all tests ok_token = test_client["auth_token"] @@ -27,6 +28,7 @@ def _setup(mock_app, test_client, test_node, database): return ok_token + def test_heartbeat(mock_app, database, test_client): """Test sending a GET request to see if app has a heartbeat""" @@ -264,8 +266,7 @@ def test_delete_patient(mock_app, database, gpx4_patients, test_client, test_nod data = json.loads(response.data) assert ( - data["message"] - == "ERROR. Could not delete a patient with ID not_a_valid_ID from database" + data["message"] == "ERROR. Could not delete a patient with ID not_a_valid_ID from database" ) # ensure no matches initially @@ -317,8 +318,7 @@ def test_patient_matches(mock_app, database, match_objs, test_client, test_node) data = json.loads(response.data) assert ( - data["message"] - == "Could not find any matches in database for patient ID unknown_patient" + data["message"] == "Could not find any matches in database for patient ID unknown_patient" ) # authorized request with valid patient From 36c1a5f757f8679247e785576977623f38451a7b Mon Sep 17 00:00:00 2001 From: Chiara Rasi Date: Mon, 13 Apr 2026 14:34:25 +0200 Subject: [PATCH 3/7] Limit duplications some more --- tests/server/test_server_responses.py | 64 +++++++++++---------------- 1 file changed, 27 insertions(+), 37 deletions(-) diff --git a/tests/server/test_server_responses.py b/tests/server/test_server_responses.py index 58859bb..98b2972 100644 --- a/tests/server/test_server_responses.py +++ b/tests/server/test_server_responses.py @@ -28,7 +28,22 @@ def _setup(mock_app, test_client, test_node, database): return ok_token +def _setup_patients(database, gpx4_patients): + """Insert demo patients into DB""" + assert len(gpx4_patients) == 2 + inserted_ids = [] + for pat in gpx4_patients: + mme_pat = mme_patient(pat, True) + inserted_ids.append(backend_add_patient(database, mme_pat)) + assert len(inserted_ids) == 2 + return inserted_ids + return inserted_ids +def _assert_valid_match_structure(match): + for res in match["results"]: + for pat in res["patients"]: + assert pat["patient"]["contact"] + assert pat["score"]["patient"] > 0 def test_heartbeat(mock_app, database, test_client): """Test sending a GET request to see if app has a heartbeat""" @@ -368,70 +383,45 @@ def test_patient_matches(mock_app, database, match_objs, test_client, test_node) def test_match_hgnc_symbol_patient( mock_app, gpx4_patients, test_client, test_node, database, mocked_ensemble_responses ): - """Testing matching patient with gene symbol against patientMatcher database (internal matching)""" - - # Setup authorized client and node ok_token = _setup(mock_app, test_client, test_node, database) query_patient = {"patient": gpx4_patients[0]} assert query_patient["patient"]["genomicFeatures"][0]["gene"]["id"] == "GPX4" - # Load 2 test patients into mock database - assert len(gpx4_patients) == 2 - inserted_ids = [] - for pat in gpx4_patients: - mme_pat = mme_patient(pat, True) - inserted_ids.append(backend_add_patient(database, mme_pat)) - assert len(inserted_ids) == 2 + _setup_patients(database, gpx4_patients) - # Validate API response validator - malformed_match_results = {"results": "fakey_results"} - assert validate_response(malformed_match_results) == 422 - - # Ensure no matches exist initially + assert validate_response({"results": "fakey_results"}) == 422 assert database["matches"].find_one() is None - # Send match request response = mock_app.test_client().post( MATCH_ENDPOINT, data=json.dumps(query_patient), headers=auth_headers(ok_token), ) - assert response.status_code == 200 + assert response.status_code == 200 data = json.loads(response.data) + assert isinstance(data["results"], list) assert len(data["results"]) == 2 assert "patient" in data["results"][0] assert "score" in data["results"][0] assert "contact" in data["results"][0]["patient"] - # Verify DB match object match = database["matches"].find_one() - for res in match["results"]: - for pat in res["patients"]: - assert pat["patient"]["contact"] - assert pat["score"]["patient"] > 0 + _assert_valid_match_structure(match) @responses.activate def test_match_ensembl_patient( mock_app, test_client, gpx4_patients, test_node, database, mocked_ensemble_responses ): - """Test matching patient with Ensembl gene against patientMatcher database (internal matching)""" - - # Setup authorized client + node ok_token = _setup(mock_app, test_client, test_node, database) query_patient = {"patient": mme_patient(gpx4_patients[0], True)} assert query_patient["patient"]["genomicFeatures"][0]["gene"]["id"].startswith("ENSG") - assert len(gpx4_patients) == 2 - inserted_ids = [] - for pat in gpx4_patients: - mme_pat = mme_patient(pat, True) - inserted_ids.append(backend_add_patient(database, mme_pat)) - assert len(inserted_ids) == 2 + _setup_patients(database, gpx4_patients) assert database["matches"].find_one() is None @@ -440,9 +430,10 @@ def test_match_ensembl_patient( data=json.dumps(query_patient), headers=auth_headers(ok_token), ) - assert response.status_code == 200 + assert response.status_code == 200 data = json.loads(response.data) + assert isinstance(data["results"], list) assert len(data["results"]) == 2 assert "patient" in data["results"][0] @@ -450,12 +441,11 @@ def test_match_ensembl_patient( assert "contact" in data["results"][0]["patient"] match = database["matches"].find_one() - for res in match["results"]: - for pat in res["patients"]: - assert pat["patient"]["contact"] - assert pat["score"]["patient"] > 0 + _assert_valid_match_structure(match) - assert match["data"]["patient"]["genomicFeatures"][0]["gene"]["_geneName"] == "GPX4" + assert ( + match["data"]["patient"]["genomicFeatures"][0]["gene"]["_geneName"] == "GPX4" + ) @responses.activate From b656930b0124d099633c53b09be61b1517d26dcc Mon Sep 17 00:00:00 2001 From: Chiara Rasi Date: Mon, 13 Apr 2026 14:36:14 +0200 Subject: [PATCH 4/7] Same black as actions --- tests/server/test_server_responses.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/server/test_server_responses.py b/tests/server/test_server_responses.py index 98b2972..e5262ed 100644 --- a/tests/server/test_server_responses.py +++ b/tests/server/test_server_responses.py @@ -28,6 +28,7 @@ def _setup(mock_app, test_client, test_node, database): return ok_token + def _setup_patients(database, gpx4_patients): """Insert demo patients into DB""" assert len(gpx4_patients) == 2 @@ -39,11 +40,14 @@ def _setup_patients(database, gpx4_patients): return inserted_ids return inserted_ids + def _assert_valid_match_structure(match): for res in match["results"]: for pat in res["patients"]: assert pat["patient"]["contact"] assert pat["score"]["patient"] > 0 + + def test_heartbeat(mock_app, database, test_client): """Test sending a GET request to see if app has a heartbeat""" @@ -443,9 +447,7 @@ def test_match_ensembl_patient( match = database["matches"].find_one() _assert_valid_match_structure(match) - assert ( - match["data"]["patient"]["genomicFeatures"][0]["gene"]["_geneName"] == "GPX4" - ) + assert match["data"]["patient"]["genomicFeatures"][0]["gene"]["_geneName"] == "GPX4" @responses.activate From 76bc991d4cd2d0b1f64bebb335ed88b2306709df Mon Sep 17 00:00:00 2001 From: Chiara Rasi Date: Mon, 13 Apr 2026 14:39:19 +0200 Subject: [PATCH 5/7] And some more --- tests/server/test_server_responses.py | 50 +++++++++++---------------- 1 file changed, 21 insertions(+), 29 deletions(-) diff --git a/tests/server/test_server_responses.py b/tests/server/test_server_responses.py index e5262ed..942ed51 100644 --- a/tests/server/test_server_responses.py +++ b/tests/server/test_server_responses.py @@ -38,7 +38,25 @@ def _setup_patients(database, gpx4_patients): inserted_ids.append(backend_add_patient(database, mme_pat)) assert len(inserted_ids) == 2 return inserted_ids - return inserted_ids + + +def _run_match_request(mock_app, endpoint, query_patient, ok_token): + response = mock_app.test_client().post( + endpoint, + data=json.dumps(query_patient), + headers=auth_headers(ok_token), + ) + + assert response.status_code == 200 + data = json.loads(response.data) + + assert isinstance(data["results"], list) + assert len(data["results"]) == 2 + assert "patient" in data["results"][0] + assert "score" in data["results"][0] + assert "contact" in data["results"][0]["patient"] + + return data def _assert_valid_match_structure(match): @@ -397,20 +415,7 @@ def test_match_hgnc_symbol_patient( assert validate_response({"results": "fakey_results"}) == 422 assert database["matches"].find_one() is None - response = mock_app.test_client().post( - MATCH_ENDPOINT, - data=json.dumps(query_patient), - headers=auth_headers(ok_token), - ) - - assert response.status_code == 200 - data = json.loads(response.data) - - assert isinstance(data["results"], list) - assert len(data["results"]) == 2 - assert "patient" in data["results"][0] - assert "score" in data["results"][0] - assert "contact" in data["results"][0]["patient"] + data = _run_match_request(mock_app, MATCH_ENDPOINT, query_patient, ok_token) match = database["matches"].find_one() _assert_valid_match_structure(match) @@ -429,20 +434,7 @@ def test_match_ensembl_patient( assert database["matches"].find_one() is None - response = mock_app.test_client().post( - MATCH_ENDPOINT, - data=json.dumps(query_patient), - headers=auth_headers(ok_token), - ) - - assert response.status_code == 200 - data = json.loads(response.data) - - assert isinstance(data["results"], list) - assert len(data["results"]) == 2 - assert "patient" in data["results"][0] - assert "score" in data["results"][0] - assert "contact" in data["results"][0]["patient"] + data = _run_match_request(mock_app, MATCH_ENDPOINT, query_patient, ok_token) match = database["matches"].find_one() _assert_valid_match_structure(match) From 5fc8b9bc13e2693eb442f92d348a19bea0ce086b Mon Sep 17 00:00:00 2001 From: Chiara Rasi Date: Mon, 13 Apr 2026 14:47:43 +0200 Subject: [PATCH 6/7] Removed unused variable --- tests/server/test_server_responses.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/server/test_server_responses.py b/tests/server/test_server_responses.py index 942ed51..332f57d 100644 --- a/tests/server/test_server_responses.py +++ b/tests/server/test_server_responses.py @@ -415,7 +415,7 @@ def test_match_hgnc_symbol_patient( assert validate_response({"results": "fakey_results"}) == 422 assert database["matches"].find_one() is None - data = _run_match_request(mock_app, MATCH_ENDPOINT, query_patient, ok_token) + _run_match_request(mock_app, MATCH_ENDPOINT, query_patient, ok_token) match = database["matches"].find_one() _assert_valid_match_structure(match) @@ -434,7 +434,7 @@ def test_match_ensembl_patient( assert database["matches"].find_one() is None - data = _run_match_request(mock_app, MATCH_ENDPOINT, query_patient, ok_token) + _run_match_request(mock_app, MATCH_ENDPOINT, query_patient, ok_token) match = database["matches"].find_one() _assert_valid_match_structure(match) From 3e779f89b3bb02e094111c556c0eada8a6d6518b Mon Sep 17 00:00:00 2001 From: Chiara Rasi Date: Mon, 13 Apr 2026 14:52:24 +0200 Subject: [PATCH 7/7] Updated changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9cc7765..90ac3f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Updated versions of external actions and MongoDB in GitHub workflows (#374) - Allow updating contact's email and href separately using the command line (#381) - Conftest file to reflect a patient's contact with email, roles and additionalContacts (#383) +- Refactored endpoints tests to avoid duplicated code (#388) ### Fixed - Fixed typo on conda installation docs (#373) - Parsing and saving `additionalContacts` field when a patient is saved using the endpoint (#386)