about summary refs log tree commit diff
path: root/gn2/tests/unit/base
diff options
context:
space:
mode:
Diffstat (limited to 'gn2/tests/unit/base')
-rw-r--r--gn2/tests/unit/base/__init__.py0
-rw-r--r--gn2/tests/unit/base/test_data_set.py238
-rw-r--r--gn2/tests/unit/base/test_general_object.py40
-rw-r--r--gn2/tests/unit/base/test_mrna_assay_tissue_data.py81
-rw-r--r--gn2/tests/unit/base/test_species.py80
-rw-r--r--gn2/tests/unit/base/test_trait.py262
-rw-r--r--gn2/tests/unit/base/test_webqtl_case_data.py40
7 files changed, 741 insertions, 0 deletions
diff --git a/gn2/tests/unit/base/__init__.py b/gn2/tests/unit/base/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/gn2/tests/unit/base/__init__.py
diff --git a/gn2/tests/unit/base/test_data_set.py b/gn2/tests/unit/base/test_data_set.py
new file mode 100644
index 00000000..7341314c
--- /dev/null
+++ b/gn2/tests/unit/base/test_data_set.py
@@ -0,0 +1,238 @@
+"""Tests for wqflask/base/data_set.py"""
+
+import unittest
+from unittest import mock
+from dataclasses import dataclass
+from gn3.monads import MonadicDict
+
+from gn2.wqflask import app
+from gn2.base.data_set import DatasetType
+from gn2.base.data_set.dataset import DataSet
+
+GEN_MENU_JSON = """
+{
+  "datasets": {
+    "human": {
+      "HLC": {
+        "Liver mRNA": [
+          [
+            "320",
+            "HLC_0311",
+            "GSE9588 Human Liver Normal (Mar11) Both Sexes"
+          ]
+        ],
+        "Phenotypes": [
+          [
+            "635",
+            "HLCPublish",
+            "HLC Published Phenotypes"
+          ]
+        ]
+      }
+    },
+    "mouse": {
+      "BXD": {
+        "Genotypes": [
+          [
+            "600",
+            "BXDGeno",
+            "BXD Genotypes"
+          ]
+        ],
+        "Hippocampus mRNA": [
+          [
+            "112",
+            "HC_M2_0606_P",
+            "Hippocampus Consortium M430v2 (Jun06) PDNN"
+          ]
+        ],
+        "Phenotypes": [
+          [
+            "602",
+            "BXDPublish",
+            "BXD Published Phenotypes"
+          ]
+        ]
+      }
+    }
+  },
+  "groups": {
+    "human": [
+      [
+        "HLC",
+        "Liver: Normal Gene Expression with Genotypes (Merck)",
+        "Family:None"
+      ]
+    ],
+    "mouse": [
+      [
+        "BXD",
+        "BXD",
+        "Family:None"
+      ]
+    ]
+  },
+  "species": [
+    [
+      "human",
+      "Human"
+    ],
+    [
+      "mouse",
+      "Mouse"
+    ]
+  ],
+  "types": {
+    "human": {
+      "HLC": [
+        [
+          "Phenotypes",
+          "Traits and Cofactors",
+          "Phenotypes"
+        ],
+        [
+          "Liver mRNA",
+          "Liver mRNA",
+          "Molecular Trait Datasets"
+        ]
+      ]
+    },
+    "mouse": {
+      "BXD": [
+        [
+          "Phenotypes",
+          "Traits and Cofactors",
+          "Phenotypes"
+        ],
+        [
+          "Genotypes",
+          "DNA Markers and SNPs",
+          "Genotypes"
+        ],
+        [
+          "Hippocampus mRNA",
+          "Hippocampus mRNA",
+          "Molecular Trait Datasets"
+        ]
+      ]
+    }
+  }
+}
+"""
+
+class MockPhenotypeDataset(DataSet):
+    def setup(self):
+        self.type = "Publish"
+        self.query_for_group = ""
+        self.group = ""
+
+
+    def check_confidentiality(self):
+        pass
+
+    def retrieve_other_names(self):
+        pass
+
+@dataclass
+class MockGroup:
+    name = "Group"
+
+class TestDataSetTypes(unittest.TestCase):
+    """Tests for the DataSetType class"""
+
+    def setUp(self):
+        self.test_dataset = """
+            {
+                "AD-cases-controls-MyersGeno": "Geno",
+                "AD-cases-controls-MyersPublish": "Publish",
+                "AKXDGeno": "Geno",
+                "AXBXAGeno": "Geno",
+                "AXBXAPublish": "Publish",
+                "Aging-Brain-UCIPublish": "Publish",
+                "All Phenotypes": "Publish",
+                "B139_K_1206_M": "ProbeSet",
+                "B139_K_1206_R": "ProbeSet"
+            }
+            """
+        self.app_context = app.app_context()
+        self.app_context.push()
+
+    def tearDown(self):
+        self.app_context.pop()
+
+    def test_data_set_type(self):
+        """Test that DatasetType returns correctly if the Redis Instance is not empty
+        and the name variable exists in the dictionary
+
+        """
+        with app.app_context():
+            redis_mock = mock.Mock()
+            cursor_mock = mock.Mock()
+            redis_mock.get.return_value = self.test_dataset
+            self.assertEqual(DatasetType(redis_mock)
+                             ("All Phenotypes", redis_mock, cursor_mock), "Publish")
+            redis_mock.get.assert_called_once_with("dataset_structure")
+
+    @mock.patch('base.data_set.datasettype.requests.get')
+    def test_data_set_type_with_empty_redis(self, request_mock):
+        """Test that DatasetType returns correctly if the Redis Instance is empty and
+        the name variable exists in the dictionary
+
+        """
+        with app.app_context():
+            request_mock.return_value.content = GEN_MENU_JSON
+            redis_mock = mock.Mock()
+            cursor_mock = mock.Mock()
+            redis_mock.get.return_value = None
+            data_set = DatasetType(redis_mock)
+            self.assertEqual(data_set("BXDGeno", redis_mock, cursor_mock),
+                             "Geno")
+            self.assertEqual(data_set("BXDPublish", redis_mock, cursor_mock),
+                             "Publish")
+            self.assertEqual(data_set("HLC_0311", redis_mock, cursor_mock),
+                             "ProbeSet")
+
+            redis_mock.set.assert_called_once_with(
+                "dataset_structure",
+                ('{"HLC_0311": "ProbeSet", '
+                 '"HLCPublish": "Publish", '
+                 '"BXDGeno": "Geno", '
+                 '"HC_M2_0606_P": "ProbeSet", '
+                 '"BXDPublish": "Publish"}'))
+
+
+class TestDatasetAccessionId(unittest.TestCase):
+    """Tests for the DataSetType class"""
+
+    @mock.patch("base.data_set.dataset.query_sql")
+    @mock.patch("base.data_set.dataset.DatasetGroup")
+    def test_get_accession_id(self, mock_dataset_group, mock_query_sql):
+        def mock_fn():
+            yield MonadicDict({"accession_id": 7})
+        mock_dataset_group.return_value = MockGroup()
+        mock_query_sql.return_value = mock_fn()
+        sample_dataset = MockPhenotypeDataset(
+            name="BXD-LongevityPublish",
+            get_samplelist=False,
+            group_name="BXD",
+            redis_conn=mock.Mock()
+        )
+        sample_dataset\
+            .accession_id\
+            .bind(lambda x: self.assertEqual(7, x))
+
+    @mock.patch("base.data_set.dataset.query_sql")
+    @mock.patch("base.data_set.dataset.DatasetGroup")
+    def test_get_accession_id_empty_return(self, mock_dataset_group,
+                                           mock_query_sql):
+        mock_dataset_group.return_value = MockGroup()
+        mock_query_sql.return_value = None
+        sample_dataset = MockPhenotypeDataset(
+            name="BXD-LongevityPublish",
+            get_samplelist=False,
+            group_name="BXD",
+            redis_conn=mock.Mock()
+        )
+        sample_dataset\
+            .accession_id\
+            .bind(lambda x: self.assertNone(x))
diff --git a/gn2/tests/unit/base/test_general_object.py b/gn2/tests/unit/base/test_general_object.py
new file mode 100644
index 00000000..1301f18b
--- /dev/null
+++ b/gn2/tests/unit/base/test_general_object.py
@@ -0,0 +1,40 @@
+import unittest
+
+from gn2.base.GeneralObject import GeneralObject
+
+
+class TestGeneralObjectTests(unittest.TestCase):
+    """
+    Test the GeneralObject base class
+    """
+
+    def test_object_contents(self):
+        """Test whether base contents are stored properly"""
+        test_obj = GeneralObject("a", "b", "c")
+        self.assertEqual("abc", ''.join(test_obj.contents))
+        self.assertEqual(len(test_obj), 0)
+
+    def test_object_dict(self):
+        """Test whether the base class is printed properly"""
+        test_obj = GeneralObject("a", name="test", value=1)
+        self.assertEqual(str(test_obj), "name = test\nvalue = 1\n")
+        self.assertEqual(
+            repr(test_obj), "contents = ['a']\nname = test\nvalue = 1\n")
+        self.assertEqual(len(test_obj), 2)
+        self.assertEqual(test_obj["value"], 1)
+        test_obj["test"] = 1
+        self.assertEqual(test_obj["test"], 1)
+
+    def test_get_attribute(self):
+        "Test that getattr works"
+        test_obj = GeneralObject("a", name="test", value=1)
+        self.assertEqual(getattr(test_obj, "value", None), 1)
+        self.assertEqual(getattr(test_obj, "non-existent", None), None)
+
+    def test_object_comparisons(self):
+        "Test that 2 objects of the same length are equal"
+        test_obj1 = GeneralObject("a", name="test", value=1)
+        test_obj2 = GeneralObject("b", name="test2", value=2)
+        test_obj3 = GeneralObject("a", name="test", x=1, y=2)
+        self.assertTrue(test_obj1 == test_obj2)
+        self.assertFalse(test_obj1 == test_obj3)
diff --git a/gn2/tests/unit/base/test_mrna_assay_tissue_data.py b/gn2/tests/unit/base/test_mrna_assay_tissue_data.py
new file mode 100644
index 00000000..5bc28ffa
--- /dev/null
+++ b/gn2/tests/unit/base/test_mrna_assay_tissue_data.py
@@ -0,0 +1,81 @@
+import pytest
+from gn2.base.mrna_assay_tissue_data import MrnaAssayTissueData
+
+
+@pytest.mark.parametrize(
+    ('gene_symbols', 'expected_query', 'sql_fetch_all_results'),
+    (
+        (None,
+         (("SELECT t.Symbol, t.GeneId, t.DataId, "
+           "t.Chr, t.Mb, t.description, "
+           "t.Probe_Target_Description "
+           "FROM (SELECT Symbol, "
+           "max(Mean) AS maxmean "
+           "FROM TissueProbeSetXRef WHERE "
+           "TissueProbeSetFreezeId=1 AND "
+           "Symbol != '' AND Symbol IS NOT "
+           "Null GROUP BY Symbol) "
+           "AS x INNER JOIN TissueProbeSetXRef "
+           "AS t ON t.Symbol = x.Symbol "
+           "AND t.Mean = x.maxmean"),),
+         (("symbol", "gene_id",
+           "data_id", "chr", "mb",
+           "description",
+           "probe_target_description"),)),
+        (["k1", "k2", "k3"],
+         ("SELECT t.Symbol, t.GeneId, t.DataId, "
+          "t.Chr, t.Mb, t.description, "
+          "t.Probe_Target_Description FROM (SELECT Symbol, "
+          "max(Mean) AS maxmean "
+          "FROM TissueProbeSetXRef WHERE "
+          "TissueProbeSetFreezeId=1 AND "
+          "Symbol IN (%s, %s, %s) "
+          "GROUP BY Symbol) AS x INNER JOIN "
+          "TissueProbeSetXRef AS "
+          "t ON t.Symbol = x.Symbol "
+          "AND t.Mean = x.maxmean",
+          ("k1", "k2", "k3")),
+         (("k1", "203",
+           "112", "xy", "20.11",
+           "Sample Description",
+           "Sample Probe Target Description"),)),
+    ),
+)
+def test_mrna_assay_tissue_data_initialisation(mocker, gene_symbols,
+                                               expected_query,
+                                               sql_fetch_all_results):
+    mock_conn = mocker.MagicMock()
+    with mock_conn.cursor() as cursor:
+        cursor.fetchall.return_value = sql_fetch_all_results
+        MrnaAssayTissueData(conn=mock_conn, gene_symbols=gene_symbols)
+        cursor.execute.assert_called_with(*expected_query)
+
+
+def test_get_trait_symbol_and_tissue_values(mocker):
+    """Test for getting trait symbol and tissue_values"""
+    mock_conn = mocker.MagicMock()
+    with mock_conn.cursor() as cursor:
+        cursor.fetchall.side_effect = [
+            (("k1", "203",
+              "112", "xy", "20.11",
+              "Sample Description",
+              "Sample Probe Target Description"),),
+            (("k1", "v1"),
+             ("k2", "v2"),
+             ("k3", "v3")),
+        ]
+        _m = MrnaAssayTissueData(conn=mock_conn,
+                                 gene_symbols=["k1", "k2", "k3"])
+        assert _m.get_symbol_values_pairs() == {
+            "k1": ["v1"],
+            "k2": ["v2"],
+            "k3": ["v3"],
+        }
+        cursor.execute.assert_called_with(
+            "SELECT TissueProbeSetXRef.Symbol, "
+            "TissueProbeSetData.value FROM "
+            "TissueProbeSetXRef, TissueProbeSetData "
+            "WHERE TissueProbeSetData.Id IN (%s) "
+            "AND TissueProbeSetXRef.DataId = "
+            "TissueProbeSetData.Id",
+            ('112',))
diff --git a/gn2/tests/unit/base/test_species.py b/gn2/tests/unit/base/test_species.py
new file mode 100644
index 00000000..239e8b3f
--- /dev/null
+++ b/gn2/tests/unit/base/test_species.py
@@ -0,0 +1,80 @@
+"""Tests wqflask/base/species.py"""
+import pytest
+from gn2.base.species import TheSpecies
+from gn2.base.species import IndChromosome
+from gn2.base.species import Chromosomes
+from collections import OrderedDict
+from dataclasses import dataclass
+
+
+@dataclass
+class MockChromosome:
+    OrderId: int
+    Name: str
+    Length: int
+
+
+@dataclass
+class MockGroup:
+    name: str
+
+
+@dataclass
+class MockDataset:
+    group: MockGroup
+
+
+@pytest.mark.parametrize(
+    ("species_name", "dataset", "expected_name", "chromosome_param"),
+    (("BXD", None, "BXD", 1),
+     (None, "Random Dataset", None, 1)))
+def test_species(mocker, species_name, dataset,
+                 expected_name, chromosome_param):
+    _c = mocker.patch("base.species.Chromosomes",
+                      return_value=chromosome_param)
+    test_species = TheSpecies(dataset=dataset,
+                              species_name=species_name)
+    _c.assert_called_with(species=species_name,
+                          dataset=dataset)
+    assert test_species.name == expected_name
+    assert test_species.chromosomes == chromosome_param
+
+
+@pytest.mark.parametrize(
+    ("name", "length", "mb_length"),
+    (("Test A", 10000000, 10),
+     ("Test B", 100, 0.0001)))
+def test_create_ind_chromosome(name, length, mb_length):
+    _ind = IndChromosome(name=name, length=length)
+    assert _ind.name == name
+    assert _ind.length == length
+    assert _ind.mb_length == mb_length
+
+
+@pytest.mark.parametrize(
+    ("species", "dataset", "expected_call"),
+    (("bxd", MockDataset(MockGroup("Random")),
+      ("SELECT Chr_Length.Name, Chr_Length.OrderId, Length "
+       "FROM Chr_Length, Species WHERE "
+       "Chr_Length.SpeciesId = Species.SpeciesId AND "
+       "Species.Name = %s "
+       "ORDER BY OrderId", ("Bxd",))),
+     (None, MockDataset(MockGroup("Random")),
+      ("SELECT Chr_Length.Name, Chr_Length.OrderId, "
+       "Length FROM Chr_Length, InbredSet WHERE "
+       "Chr_Length.SpeciesId = InbredSet.SpeciesId AND "
+       "InbredSet.Name = "
+       "%s ORDER BY OrderId", ("Random",)))))
+def test_create_chromosomes(mocker, species, dataset, expected_call):
+    mock_conn = mocker.MagicMock()
+    with mock_conn.cursor() as cursor:
+        cursor.fetchall.return_value = (("1", 2, 10,),
+                                        ("2", 3, 11,),
+                                        ("4", 5, 15,),)
+        _c = Chromosomes(dataset=dataset, species=species)
+        assert _c.chromosomes(cursor) == OrderedDict([
+            ("1", IndChromosome("1", 10)),
+            ("2", IndChromosome("2", 11)),
+            ("4", IndChromosome("4", 15)),
+        ])
+        cursor.execute.assert_called_with(*expected_call)
diff --git a/gn2/tests/unit/base/test_trait.py b/gn2/tests/unit/base/test_trait.py
new file mode 100644
index 00000000..417956ae
--- /dev/null
+++ b/gn2/tests/unit/base/test_trait.py
@@ -0,0 +1,262 @@
+# -*- coding: utf-8 -*-
+"""Tests wqflask/base/trait.py"""
+import unittest
+from unittest import mock
+
+from gn2.base.trait import GeneralTrait
+from gn2.base.trait import retrieve_trait_info
+
+
+class TestResponse:
+    """Mock Test Response after a request"""
+    @property
+    def content(self):
+        """Mock the content from Requests.get(params).content"""
+        return "[1, 2, 3, 4]"
+
+
+class TestNilResponse:
+    """Mock Test Response after a request"""
+    @property
+    def content(self):
+        """Mock the content from Requests.get(params).content"""
+        return "{}"
+
+
+class MockTrait(GeneralTrait):
+    @property
+    def wikidata_alias_fmt(self):
+        return "Mock alias"
+
+
+class TestRetrieveTraitInfo(unittest.TestCase):
+    """Tests for 'retrieve_trait_info'"""
+    @mock.patch('base.trait.database_connection')
+    def test_retrieve_trait_info_with_empty_dataset(self, mock_db):
+        """Test that an exception is raised when dataset is empty"""
+        conn = mock.MagicMock()
+        mock_db.return_value.__enter__.return_value = conn
+        with self.assertRaises(ValueError):
+            retrieve_trait_info(trait=mock.MagicMock(),
+                                dataset={})
+
+    @mock.patch('base.trait.requests.get')
+    @mock.patch('base.trait.g', mock.Mock())
+    @mock.patch('base.trait.database_connection')
+    def test_retrieve_trait_info_with_empty_trait_info(self,
+                                                       mock_db,
+                                                       requests_mock):
+        """Empty trait info"""
+        conn = mock.MagicMock()
+        cursor = mock.MagicMock()
+        cursor.fetchone.return_value = {}
+        conn.cursor.return_value.__enter__.return_value = cursor
+        mock_db.return_value.__enter__.return_value = conn
+        requests_mock.return_value = TestNilResponse()
+        with self.assertRaises(KeyError):
+            retrieve_trait_info(trait=mock.MagicMock(),
+                                dataset=mock.MagicMock())
+
+    @mock.patch('base.trait.requests.get')
+    @mock.patch('base.trait.g', mock.Mock())
+    @mock.patch('base.trait.database_connection')
+    def test_retrieve_trait_info_with_non_empty_trait_info(self,
+                                                           mock_db,
+                                                           requests_mock):
+        """Test that attributes are set"""
+        mock_dataset = mock.MagicMock()
+        conn = mock.MagicMock()
+        cursor = mock.MagicMock()
+        cursor.fetchone.return_value = [1, 2, 3, 4]
+        conn.cursor.return_value.__enter__.return_value = cursor
+        mock_db.return_value.__enter__.return_value = conn
+        requests_mock.return_value = TestResponse()
+        type(mock_dataset).display_fields = mock.PropertyMock(
+            return_value=["a", "b", "c", "d"])
+        test_trait = retrieve_trait_info(trait=MockTrait(dataset=mock_dataset),
+                                         dataset=mock_dataset)
+        self.assertEqual(test_trait.a, 1)
+        self.assertEqual(test_trait.b, 2)
+        self.assertEqual(test_trait.c, 3)
+        self.assertEqual(test_trait.d, 4)
+
+    @mock.patch('base.trait.requests.get')
+    @mock.patch('base.trait.g', mock.Mock())
+    @mock.patch('base.trait.database_connection')
+    def test_retrieve_trait_info_utf8_parsing(self,
+                                              mock_db,
+                                              requests_mock):
+        """Test that utf-8 strings are parsed correctly"""
+        utf_8_string = "test_string"
+        conn = mock.MagicMock()
+        mock_db.return_value.__enter__.return_value = conn
+        mock_dataset = mock.MagicMock()
+        requests_mock.return_value = TestResponse()
+        type(mock_dataset).display_fields = mock.PropertyMock(
+            return_value=["a", "b", "c", "d"])
+        type(mock_dataset).type = 'Publish'
+
+        mock_trait = MockTrait(
+            dataset=mock_dataset,
+            pre_publication_description=utf_8_string
+        )
+        trait_attrs = {
+            "group_code": "test_code",
+            "pre_publication_description": "test_pre_pub",
+            "pre_publication_abbreviation": "ファイルを画面毎に見て行くには、次のコマンドを使います。",
+            "post_publication_description": None,
+            "pubmed_id": None,
+            'year': "2020",
+            "authors": "Jane Doe かいと",
+        }
+        for key, val in list(trait_attrs.items()):
+            setattr(mock_trait, key, val)
+        test_trait = retrieve_trait_info(trait=mock_trait,
+                                         dataset=mock_dataset)
+        self.assertEqual(test_trait.abbreviation,
+                         "ファイルを画面毎に見て行くには、次のコマンドを使います。")
+        self.assertEqual(test_trait.authors,
+                         "Jane Doe かいと")
+
+
+    @unittest.skip("Too complicated")
+    @mock.patch('base.trait.requests.get')
+    @mock.patch('base.trait.database_connection')
+    @mock.patch('base.trait.get_resource_id')
+    def test_retrieve_trait_info_with_non_empty_lrs(self,
+                                                    resource_id_mock,
+                                                    mock_db,
+                                                    requests_mock):
+        """Test retrieve trait info when lrs has a value"""
+        resource_id_mock.return_value = 1
+        conn = mock.MagicMock()
+        mock_db.return_value.__enter__.return_value = conn
+        with conn.cursor() as cursor:
+            cursor.fetchone.side_effect = [
+                # trait_info = g.db.execute(query).fetchone()
+                [1, 2, 3, 4],
+                # trait_qtl = g.db.execute(query).fetchone()
+                [1, 2.37, 3, 4, 5],
+                # trait_info = g.db.execute(query).fetchone()
+                [2.7333, 2.1204]
+            ]
+            requests_mock.return_value = None
+
+            mock_dataset = mock.MagicMock()
+            type(mock_dataset).display_fields = mock.PropertyMock(
+                return_value=["a", "b", "c", "d"])
+            type(mock_dataset).type = "ProbeSet"
+            type(mock_dataset).name = "RandomName"
+
+            mock_trait = MockTrait(
+                dataset=mock_dataset,
+                pre_publication_description="test_string"
+            )
+            trait_attrs = {
+                "description": "some description",
+                "probe_target_description": "some description",
+                "cellid": False,
+                "chr": 2.733,
+                "mb": 2.1204
+            }
+
+            for key, val in list(trait_attrs.items()):
+                setattr(mock_trait, key, val)
+            test_trait = retrieve_trait_info(trait=mock_trait,
+                                             dataset=mock_dataset,
+                                             get_qtl_info=True)
+            self.assertEqual(test_trait.LRS_score_repr,
+                             "2.4")
+
+    @unittest.skip("Too complicated")
+    @mock.patch('base.trait.requests.get')
+    @mock.patch('base.trait.g')
+    @mock.patch('base.trait.get_resource_id')
+    def test_retrieve_trait_info_with_empty_lrs_field(self,
+                                                      resource_id_mock,
+                                                      g_mock,
+                                                      requests_mock):
+        """Test retrieve trait info with empty lrs field"""
+        resource_id_mock.return_value = 1
+        g_mock.db.execute.return_value.fetchone = mock.Mock()
+        g_mock.db.execute.return_value.fetchone.side_effect = [
+            [1, 2, 3, 4],  # trait_info = g.db.execute(query).fetchone()
+            [1, None, 3, 4, 5],  # trait_qtl = g.db.execute(query).fetchone()
+            [2, 3]  # trait_info = g.db.execute(query).fetchone()
+        ]
+        requests_mock.return_value = None
+
+        mock_dataset = mock.MagicMock()
+        type(mock_dataset).display_fields = mock.PropertyMock(
+            return_value=["a", "b", "c", "d"])
+        type(mock_dataset).type = "ProbeSet"
+        type(mock_dataset).name = "RandomName"
+
+        mock_trait = MockTrait(
+            dataset=mock_dataset,
+            pre_publication_description="test_string"
+        )
+        trait_attrs = {
+            "description": "some description",
+            "probe_target_description": "some description",
+            "cellid": False,
+            "chr": 2.733,
+            "mb": 2.1204
+        }
+
+        for key, val in list(trait_attrs.items()):
+            setattr(mock_trait, key, val)
+        test_trait = retrieve_trait_info(trait=mock_trait,
+                                         dataset=mock_dataset,
+                                         get_qtl_info=True)
+        self.assertEqual(test_trait.LRS_score_repr,
+                         "N/A")
+        self.assertEqual(test_trait.LRS_location_repr,
+                         "Chr2: 3.000000")
+        
+    @unittest.skip("Too complicated")
+    @mock.patch('base.trait.requests.get')
+    @mock.patch('base.trait.g')
+    @mock.patch('base.trait.get_resource_id')
+    def test_retrieve_trait_info_with_empty_chr_field(self,
+                                                      resource_id_mock,
+                                                      g_mock,
+                                                      requests_mock):
+        """Test retrieve trait info with empty chr field"""
+        resource_id_mock.return_value = 1
+        g_mock.db.execute.return_value.fetchone = mock.Mock()
+        g_mock.db.execute.return_value.fetchone.side_effect = [
+            [1, 2, 3, 4],  # trait_info = g.db.execute(query).fetchone()
+            [1, 2, 3, 4, 5],  # trait_qtl = g.db.execute(query).fetchone()
+            [None, 3]  # trait_info = g.db.execute(query).fetchone()
+        ]
+
+        requests_mock.return_value = None
+
+        mock_dataset = mock.MagicMock()
+        type(mock_dataset).display_fields = mock.PropertyMock(
+            return_value=["a", "b", "c", "d"])
+        type(mock_dataset).type = "ProbeSet"
+        type(mock_dataset).name = "RandomName"
+
+        mock_trait = MockTrait(
+            dataset=mock_dataset,
+            pre_publication_description="test_string"
+        )
+        trait_attrs = {
+            "description": "some description",
+            "probe_target_description": "some description",
+            "cellid": False,
+            "chr": 2.733,
+            "mb": 2.1204
+        }
+
+        for key, val in list(trait_attrs.items()):
+            setattr(mock_trait, key, val)
+        test_trait = retrieve_trait_info(trait=mock_trait,
+                                         dataset=mock_dataset,
+                                         get_qtl_info=True)
+        self.assertEqual(test_trait.LRS_score_repr,
+                         "N/A")
+        self.assertEqual(test_trait.LRS_location_repr,
+                         "N/A")
diff --git a/gn2/tests/unit/base/test_webqtl_case_data.py b/gn2/tests/unit/base/test_webqtl_case_data.py
new file mode 100644
index 00000000..250b8358
--- /dev/null
+++ b/gn2/tests/unit/base/test_webqtl_case_data.py
@@ -0,0 +1,40 @@
+"""Tests for wqflask/base/webqtlCaseData.py"""
+import unittest
+
+from gn2.wqflask import app  # Required because of utility.tools in webqtlCaseData.py
+from gn2.base.webqtlCaseData import webqtlCaseData
+
+
+class TestWebqtlCaseData(unittest.TestCase):
+    """Tests for WebqtlCaseData class"""
+
+    def setUp(self):
+        self.w = webqtlCaseData(name="Test",
+                                value=0,
+                                variance=0.0,
+                                num_cases=10,
+                                name2="Test2")
+
+    def test_webqtl_case_data_repr(self):
+        self.assertEqual(
+            repr(self.w),
+            "<webqtlCaseData> value=0.000 variance=0.000 ndata=10 name=Test name2=Test2"
+        )
+
+    def test_class_outlier(self):
+        self.assertEqual(self.w.class_outlier, "")
+
+    def test_display_value(self):
+        self.assertEqual(self.w.display_value, "0.000")
+        self.w.value = None
+        self.assertEqual(self.w.display_value, "x")
+
+    def test_display_variance(self):
+        self.assertEqual(self.w.display_variance, "0.000")
+        self.w.variance = None
+        self.assertEqual(self.w.display_variance, "x")
+
+    def test_display_num_cases(self):
+        self.assertEqual(self.w.display_num_cases, "10")
+        self.w.num_cases = None
+        self.assertEqual(self.w.display_num_cases, "x")