about summary refs log tree commit diff
path: root/tests/integration
diff options
context:
space:
mode:
Diffstat (limited to 'tests/integration')
-rw-r--r--tests/integration/conftest.py24
-rw-r--r--tests/integration/test_correlation.py8
-rw-r--r--tests/integration/test_gemma.py14
-rw-r--r--tests/integration/test_general.py8
-rw-r--r--tests/integration/test_partial_correlations.py225
-rw-r--r--tests/integration/test_wgcna.py3
6 files changed, 280 insertions, 2 deletions
diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py
new file mode 100644
index 0000000..be927a4
--- /dev/null
+++ b/tests/integration/conftest.py
@@ -0,0 +1,24 @@
+"""Module that holds fixtures for integration tests"""
+import pytest
+
+from gn3.app import create_app
+from gn3.db_utils import database_connector
+
+@pytest.fixture(scope="session")
+def client():
+    """Create a test client fixture for tests"""
+    # Do some setup
+    app = create_app()
+    app.config.update({"TESTING": True})
+    app.testing = True
+    yield app.test_client()
+    # Do some teardown/cleanup
+
+
+@pytest.fixture
+def db_conn():
+    """Create a db connection fixture for tests"""
+    ## Update this to use temp db once that is in place
+    conn = database_connector()
+    yield conn
+    conn.close()
diff --git a/tests/integration/test_correlation.py b/tests/integration/test_correlation.py
index bdd9bce..d52ab01 100644
--- a/tests/integration/test_correlation.py
+++ b/tests/integration/test_correlation.py
@@ -1,6 +1,7 @@
 """module contains integration tests for correlation"""
 from unittest import TestCase
 from unittest import mock
+import pytest
 from gn3.app import create_app
 
 
@@ -10,6 +11,7 @@ class CorrelationIntegrationTest(TestCase):
     def setUp(self):
         self.app = create_app().test_client()
 
+    @pytest.mark.integration_test
     @mock.patch("gn3.api.correlation.compute_all_sample_correlation")
     def test_sample_r_correlation(self, mock_compute_samples):
         """Test /api/correlation/sample_r/{method}"""
@@ -61,6 +63,7 @@ class CorrelationIntegrationTest(TestCase):
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.get_json(), api_response)
 
+    @pytest.mark.integration_test
     @mock.patch("gn3.api.correlation.compute_all_lit_correlation")
     @mock.patch("gn3.api.correlation.database_connector")
     def test_lit_correlation(self, database_connector, mock_compute_corr):
@@ -68,7 +71,9 @@ class CorrelationIntegrationTest(TestCase):
 
         mock_compute_corr.return_value = []
 
-        database_connector.return_value = (mock.Mock(), mock.Mock())
+        database_connector.return_value = mock.Mock()
+        database_connector.return_value.__enter__ = mock.Mock()
+        database_connector.return_value.__exit__ = mock.Mock()
 
         post_data = {"1426678_at": "68031",
                      "1426679_at": "68036",
@@ -80,6 +85,7 @@ class CorrelationIntegrationTest(TestCase):
         self.assertEqual(mock_compute_corr.call_count, 1)
         self.assertEqual(response.status_code, 200)
 
+    @pytest.mark.integration_test
     @mock.patch("gn3.api.correlation.compute_tissue_correlation")
     def test_tissue_correlation(self, mock_tissue_corr):
         """Test api/correlation/tissue_corr/{corr_method}"""
diff --git a/tests/integration/test_gemma.py b/tests/integration/test_gemma.py
index f871173..0515539 100644
--- a/tests/integration/test_gemma.py
+++ b/tests/integration/test_gemma.py
@@ -7,6 +7,8 @@ from dataclasses import dataclass
 from typing import Callable
 from unittest import mock
 
+import pytest
+
 from gn3.app import create_app
 
 
@@ -30,6 +32,7 @@ class GemmaAPITest(unittest.TestCase):
             "TMPDIR": "/tmp"
         }).test_client()
 
+    @pytest.mark.integration_test
     @mock.patch("gn3.api.gemma.run_cmd")
     def test_get_version(self, mock_run_cmd):
         """Test that the correct response is returned"""
@@ -38,6 +41,7 @@ class GemmaAPITest(unittest.TestCase):
         self.assertEqual(response.get_json(), {"status": 0, "output": "v1.9"})
         self.assertEqual(response.status_code, 200)
 
+    @pytest.mark.integration_test
     @mock.patch("gn3.api.gemma.redis.Redis")
     def test_check_cmd_status(self, mock_redis):
         """Test that you can check the status of a given command"""
@@ -52,6 +56,7 @@ class GemmaAPITest(unittest.TestCase):
             name="cmd::2021-02-1217-3224-3224-1234", key="status")
         self.assertEqual(response.get_json(), {"status": "test"})
 
+    @pytest.mark.integration_test
     @mock.patch("gn3.api.gemma.queue_cmd")
     @mock.patch("gn3.computations.gemma.get_hash_of_files")
     @mock.patch("gn3.api.gemma.jsonfile_to_dict")
@@ -94,6 +99,7 @@ class GemmaAPITest(unittest.TestCase):
                 "unique_id": "my-unique-id"
             })
 
+    @pytest.mark.integration_test
     @mock.patch("gn3.api.gemma.queue_cmd")
     @mock.patch("gn3.computations.gemma.get_hash_of_files")
     @mock.patch("gn3.api.gemma.jsonfile_to_dict")
@@ -137,6 +143,7 @@ class GemmaAPITest(unittest.TestCase):
                 "unique_id": "my-unique-id"
             })
 
+    @pytest.mark.integration_test
     @mock.patch("gn3.api.gemma.queue_cmd")
     @mock.patch("gn3.computations.gemma.get_hash_of_files")
     @mock.patch("gn3.api.gemma.jsonfile_to_dict")
@@ -187,6 +194,7 @@ class GemmaAPITest(unittest.TestCase):
                 "output_file": "hash-output.json"
             })
 
+    @pytest.mark.integration_test
     @mock.patch("gn3.api.gemma.queue_cmd")
     @mock.patch("gn3.computations.gemma.get_hash_of_files")
     @mock.patch("gn3.api.gemma.jsonfile_to_dict")
@@ -240,6 +248,7 @@ class GemmaAPITest(unittest.TestCase):
                 "output_file": "hash-output.json"
             })
 
+    @pytest.mark.integration_test
     @mock.patch("gn3.api.gemma.queue_cmd")
     @mock.patch("gn3.computations.gemma.get_hash_of_files")
     @mock.patch("gn3.api.gemma.jsonfile_to_dict")
@@ -292,6 +301,7 @@ class GemmaAPITest(unittest.TestCase):
                 "output_file": "hash-output.json"
             })
 
+    @pytest.mark.integration_test
     @mock.patch("gn3.api.gemma.queue_cmd")
     @mock.patch("gn3.computations.gemma.get_hash_of_files")
     @mock.patch("gn3.api.gemma.jsonfile_to_dict")
@@ -346,6 +356,7 @@ class GemmaAPITest(unittest.TestCase):
                 "output_file": "hash-output.json"
             })
 
+    @pytest.mark.integration_test
     @mock.patch("gn3.api.gemma.queue_cmd")
     @mock.patch("gn3.computations.gemma.get_hash_of_files")
     @mock.patch("gn3.api.gemma.jsonfile_to_dict")
@@ -401,6 +412,7 @@ class GemmaAPITest(unittest.TestCase):
                 "output_file": "hash-output.json"
             })
 
+    @pytest.mark.integration_test
     @mock.patch("gn3.api.gemma.queue_cmd")
     @mock.patch("gn3.computations.gemma.get_hash_of_files")
     @mock.patch("gn3.api.gemma.jsonfile_to_dict")
@@ -465,6 +477,7 @@ class GemmaAPITest(unittest.TestCase):
                 "output_file": "hash-output.json"
             })
 
+    @pytest.mark.integration_test
     @mock.patch("gn3.api.gemma.queue_cmd")
     @mock.patch("gn3.computations.gemma.get_hash_of_files")
     @mock.patch("gn3.api.gemma.jsonfile_to_dict")
@@ -530,6 +543,7 @@ class GemmaAPITest(unittest.TestCase):
                 "output_file": "hash-output.json"
             })
 
+    @pytest.mark.integration_test
     @mock.patch("gn3.api.gemma.queue_cmd")
     @mock.patch("gn3.computations.gemma.get_hash_of_files")
     @mock.patch("gn3.api.gemma.jsonfile_to_dict")
diff --git a/tests/integration/test_general.py b/tests/integration/test_general.py
index 8fc2b43..9d87449 100644
--- a/tests/integration/test_general.py
+++ b/tests/integration/test_general.py
@@ -1,8 +1,10 @@
 """Integration tests for some 'general' API endpoints"""
 import os
 import unittest
-
 from unittest import mock
+
+import pytest
+
 from gn3.app import create_app
 
 
@@ -11,6 +13,7 @@ class GeneralAPITest(unittest.TestCase):
     def setUp(self):
         self.app = create_app().test_client()
 
+    @pytest.mark.integration_test
     def test_metadata_endpoint_exists(self):
         """Test that /metadata/upload exists"""
         response = self.app.post("/api/metadata/upload/d41d86-e4ceEo")
@@ -19,6 +22,7 @@ class GeneralAPITest(unittest.TestCase):
                          {"status": 128,
                           "error": "Please provide a file!"})
 
+    @pytest.mark.integration_test
     @mock.patch("gn3.api.general.extract_uploaded_file")
     def test_metadata_file_upload(self, mock_extract_upload):
         """Test correct upload of file"""
@@ -37,6 +41,7 @@ class GeneralAPITest(unittest.TestCase):
                          {"status": 0,
                           "token": "d41d86-e4ceEo"})
 
+    @pytest.mark.integration_test
     def test_metadata_file_wrong_upload(self):
         """Test that incorrect upload return correct status code"""
         response = self.app.post("/api/metadata/upload/d41d86-e4ceEo",
@@ -47,6 +52,7 @@ class GeneralAPITest(unittest.TestCase):
                          {"status": 128,
                           "error": "gzip failed to unpack file"})
 
+    @pytest.mark.integration_test
     @mock.patch("gn3.api.general.run_cmd")
     def test_run_r_qtl(self, mock_run_cmd):
         """Test correct upload of file"""
diff --git a/tests/integration/test_partial_correlations.py b/tests/integration/test_partial_correlations.py
new file mode 100644
index 0000000..4bf352a
--- /dev/null
+++ b/tests/integration/test_partial_correlations.py
@@ -0,0 +1,225 @@
+"""Test partial correlations"""
+from unittest import mock
+
+import pytest
+
+from gn3.computations.partial_correlations import partial_correlations_entry
+
+@pytest.mark.integration_test
+@pytest.mark.parametrize(
+    "post_data", (
+        None, {}, {
+            "primary_trait": None,
+            "control_traits": None,
+            "method": None,
+            "target_db": None
+        }, {
+            "primary_trait": None,
+            "control_traits": None,
+            "method": None,
+            "target_db": "a_db"
+        }, {
+            "primary_trait": None,
+            "control_traits": None,
+            "method": "a_method",
+            "target_db": None
+        }, {
+            "primary_trait": None,
+            "control_traits": None,
+            "method": "a_method",
+            "target_db": "a_db"
+        }, {
+            "primary_trait": None,
+            "control_traits": ["a_trait", "another"],
+            "method": None,
+            "target_db": None
+        }, {
+            "primary_trait": None,
+            "control_traits": ["a_trait", "another"],
+            "method": None,
+            "target_db": "a_db"
+        }, {
+            "primary_trait": None,
+            "control_traits": ["a_trait", "another"],
+            "method": "a_method",
+            "target_db": None
+        }, {
+            "primary_trait": None,
+            "control_traits": ["a_trait", "another"],
+            "method": "a_method",
+            "target_db": "a_db"
+        }, {
+            "primary_trait": "a_trait",
+            "control_traits": None,
+            "method": None,
+            "target_db": None
+        }, {
+            "primary_trait": "a_trait",
+            "control_traits": None,
+            "method": None,
+            "target_db": "a_db"
+        }, {
+            "primary_trait": "a_trait",
+            "control_traits": None,
+            "method": "a_method",
+            "target_db": None
+        }, {
+            "primary_trait": "a_trait",
+            "control_traits": None,
+            "method": "a_method",
+            "target_db": "a_db"
+        }, {
+            "primary_trait": "a_trait",
+            "control_traits": ["a_trait", "another"],
+            "method": None,
+            "target_db": None
+        }, {
+            "primary_trait": "a_trait",
+            "control_traits": ["a_trait", "another"],
+            "method": None,
+            "target_db": "a_db"
+        }, {
+            "primary_trait": "a_trait",
+            "control_traits": ["a_trait", "another"],
+            "method": "a_method",
+            "target_db": None
+        }))
+def test_partial_correlation_api_with_missing_request_data(client, post_data):
+    """
+    Test /api/correlations/partial endpoint with various expected request data
+    missing.
+    """
+    response = client.post("/api/correlation/partial", json=post_data)
+    assert (
+        response.status_code == 400 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": "a_dataset", "trait_name": "a_name"},
+        "control_traits": [
+            {"dataset": "a_dataset", "trait_name": "a_name"},
+            {"dataset": "a_dataset2", "trait_name": "a_name2"}],
+        "method": "a_method",
+        "target_db": "a_db"
+    }, {# Publish
+        "primary_trait": {
+            "dataset": "a_Publish_dataset", "trait_name": "a_name"},
+        "control_traits": [
+            {"dataset": "a_dataset", "trait_name": "a_name"},
+            {"dataset": "a_dataset2", "trait_name": "a_name2"}],
+        "method": "a_method",
+        "target_db": "a_db"
+    }, {# Geno
+        "primary_trait": {"dataset": "a_Geno_dataset", "trait_name": "a_name"},
+        "control_traits": [
+            {"dataset": "a_dataset", "trait_name": "a_name"},
+            {"dataset": "a_dataset2", "trait_name": "a_name2"}],
+        "method": "a_method",
+        "target_db": "a_db"
+    }, {# Temp
+        "primary_trait": {"dataset": "a_Temp_dataset", "trait_name": "a_name"},
+        "control_traits": [
+            {"dataset": "a_dataset", "trait_name": "a_name"},
+            {"dataset": "a_dataset2", "trait_name": "a_name2"}],
+        "method": "a_method",
+        "target_db": "a_db"
+    }))
+def test_partial_correlation_api_with_non_existent_primary_traits(
+        client, post_data, mocker):
+    """
+    Check that the system responds appropriately in the case where the user
+    makes a request with a non-existent primary trait.
+    """
+    mocker.patch("gn3.api.correlation.redis.Redis", mock.MagicMock())
+    response = client.post("/api/correlation/partial", json=post_data)
+    assert (
+        response.status_code == 200 and response.is_json and
+        response.json.get("status") == "success")
+
+@pytest.mark.integration_test
+@pytest.mark.slow
+@pytest.mark.parametrize(
+    "post_data",
+    ({# ProbeSet
+        "primary_trait": {
+            "dataset": "UCLA_BXDBXH_CARTILAGE_V2",
+            "trait_name": "ILM103710672"},
+        "control_traits": [
+            {"dataset": "a_dataset", "trait_name": "a_name"},
+            {"dataset": "a_dataset2", "trait_name": "a_name2"}],
+        "method": "a_method",
+        "target_db": "a_db"
+    }, {# Publish
+        "primary_trait": {"dataset": "BXDPublish", "trait_name": "BXD_12557"},
+        "control_traits": [
+            {"dataset": "a_dataset", "trait_name": "a_name"},
+            {"dataset": "a_dataset2", "trait_name": "a_name2"}],
+        "method": "a_method",
+        "target_db": "a_db"
+    }, {# Geno
+        "primary_trait": {"dataset": "AKXDGeno", "trait_name": "D4Mit16"},
+        "control_traits": [
+            {"dataset": "a_dataset", "trait_name": "a_name"},
+            {"dataset": "a_dataset2", "trait_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, mocker):
+    """
+    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.
+    """
+    mocker.patch("gn3.api.correlation.redis.Redis", mock.MagicMock())
+    response = client.post("/api/correlation/partial", json=post_data)
+    assert (
+        response.status_code == 200 and response.is_json and
+        response.json.get("status") == "success")
+
+@pytest.mark.integration_test
+@pytest.mark.slow
+@pytest.mark.parametrize(
+    "primary,controls,method,target", (
+        (# Probeset
+            "UCLA_BXDBXH_CARTILAGE_V2::ILM103710672", (
+                "UCLA_BXDBXH_CARTILAGE_V2::nonExisting01",
+                "UCLA_BXDBXH_CARTILAGE_V2::nonExisting02",
+                "UCLA_BXDBXH_CARTILAGE_V2::ILM380019"),
+            "Genetic Correlation, Pearson's r", "BXDPublish"),
+        (# Publish
+            "BXDPublish::17937", (
+                "BXDPublish::17940",
+                "BXDPublish::nonExisting03"),
+            "Genetic Correlation, Spearman's rho", "BXDPublish"),
+        (# Geno
+            "AKXDGeno::D4Mit16", (
+                "AKXDGeno::D1Mit170",
+                "AKXDGeno::nonExisting04",
+                "AKXDGeno::D1Mit135",
+                "AKXDGeno::nonExisting05",
+                "AKXDGeno::nonExisting06"),
+            "SGO Literature Correlation", "BXDPublish")
+    )
+    # Temp -- the data in the database for these is ephemeral, making it
+    #         difficult to test for these without a temp database with the temp
+    #         traits data set to something we are in control of
+     )
+
+def test_part_corr_api_with_mix_of_existing_and_non_existing_control_traits(
+        db_conn, primary, controls, method, target):
+    """
+    Check that calling the function with a mix of existing and missing control
+    traits raises an warning.
+    """
+    criteria = 10
+    with pytest.warns(UserWarning):
+        partial_correlations_entry(
+            db_conn, primary, controls, method, criteria, target)
diff --git a/tests/integration/test_wgcna.py b/tests/integration/test_wgcna.py
index 078449d..5880b40 100644
--- a/tests/integration/test_wgcna.py
+++ b/tests/integration/test_wgcna.py
@@ -3,6 +3,8 @@
 from unittest import TestCase
 from unittest import mock
 
+import pytest
+
 from gn3.app import create_app
 
 
@@ -12,6 +14,7 @@ class WgcnaIntegrationTest(TestCase):
     def setUp(self):
         self.app = create_app().test_client()
 
+    @pytest.mark.integration_test
     @mock.patch("gn3.api.wgcna.call_wgcna_script")
     def test_wgcna_endpoint(self, mock_wgcna_script):
         """test /api/wgcna/run_wgcna endpoint"""