aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/integration/test_correlation.py2
-rw-r--r--tests/unit/computations/test_correlation.py48
-rw-r--r--tests/unit/computations/test_heatmap.py143
-rw-r--r--tests/unit/computations/test_slink.py311
-rw-r--r--tests/unit/db/test_datasets.py133
-rw-r--r--tests/unit/db/test_traits.py224
6 files changed, 850 insertions, 11 deletions
diff --git a/tests/integration/test_correlation.py b/tests/integration/test_correlation.py
index e67f58d..bdd9bce 100644
--- a/tests/integration/test_correlation.py
+++ b/tests/integration/test_correlation.py
@@ -80,7 +80,7 @@ class CorrelationIntegrationTest(TestCase):
self.assertEqual(mock_compute_corr.call_count, 1)
self.assertEqual(response.status_code, 200)
- @mock.patch("gn3.api.correlation.compute_all_tissue_correlation")
+ @mock.patch("gn3.api.correlation.compute_tissue_correlation")
def test_tissue_correlation(self, mock_tissue_corr):
"""Test api/correlation/tissue_corr/{corr_method}"""
mock_tissue_corr.return_value = {}
diff --git a/tests/unit/computations/test_correlation.py b/tests/unit/computations/test_correlation.py
index b1bc6ef..fc52ec1 100644
--- a/tests/unit/computations/test_correlation.py
+++ b/tests/unit/computations/test_correlation.py
@@ -1,5 +1,4 @@
"""Module contains the tests for correlation"""
-import unittest
from unittest import TestCase
from unittest import mock
@@ -16,9 +15,10 @@ from gn3.computations.correlations import fetch_lit_correlation_data
from gn3.computations.correlations import query_formatter
from gn3.computations.correlations import map_to_mouse_gene_id
from gn3.computations.correlations import compute_all_lit_correlation
-from gn3.computations.correlations import compute_all_tissue_correlation
+from gn3.computations.correlations import compute_tissue_correlation
from gn3.computations.correlations import map_shared_keys_to_values
from gn3.computations.correlations import process_trait_symbol_dict
+from gn3.computations.correlations2 import compute_correlation
class QueryableMixin:
@@ -172,7 +172,6 @@ class TestCorrelation(TestCase):
self.assertEqual(results, (filtered_this_samplelist,
filtered_target_samplelist))
- @unittest.skip("Test needs to be refactored ")
@mock.patch("gn3.computations.correlations.compute_sample_r_correlation")
@mock.patch("gn3.computations.correlations.filter_shared_sample_keys")
def test_compute_all_sample(self, filter_shared_samples, sample_r_corr):
@@ -180,7 +179,7 @@ class TestCorrelation(TestCase):
filter_shared_samples.return_value = (["1.23", "6.565", "6.456"], [
"6.266", "6.565", "6.456"])
- sample_r_corr.return_value = ([-1.0, 0.9, 6])
+ sample_r_corr.return_value = (["1419792_at", -1.0, 0.9, 6])
this_trait_data = {
"trait_id": "1455376_at",
@@ -203,13 +202,14 @@ class TestCorrelation(TestCase):
}
]
- sample_all_results = [{"1419792_at": {"corr_coeffient": -1.0,
+ sample_all_results = [{"1419792_at": {"corr_coefficient": -1.0,
"p_value": 0.9,
"num_overlap": 6}}]
self.assertEqual(compute_all_sample_correlation(
this_trait=this_trait_data, target_dataset=traits_dataset), sample_all_results)
sample_r_corr.assert_called_once_with(
+ trait_name='1419792_at',
corr_method="pearson", trait_vals=['1.23', '6.565', '6.456'],
target_samples_vals=['6.266', '6.565', '6.456'])
filter_shared_samples.assert_called_once_with(
@@ -406,17 +406,17 @@ class TestCorrelation(TestCase):
target_tissue_data = {"trait_symbol_dict": target_trait_symbol,
"symbol_tissue_vals_dict": target_symbol_tissue_vals}
- mock_tissue_corr.side_effect = [{"tissue_corr": -0.5, "tissue_p_val": 0.9,
- "tissue_number": 3},
- {"tissue_corr": 1.11, "tissue_p_val": 0.2,
- "tissue_number": 3}]
+ mock_tissue_corr.side_effect = [{"1418702_a_at": {"tissue_corr": -0.5, "tissue_p_val": 0.9,
+ "tissue_number": 3}},
+ {"1412_at": {"tissue_corr": 1.11, "tissue_p_val": 0.2,
+ "tissue_number": 3}}]
expected_results = [{"1412_at":
{"tissue_corr": 1.11, "tissue_p_val": 0.2, "tissue_number": 3}},
{"1418702_a_at":
{"tissue_corr": -0.5, "tissue_p_val": 0.9, "tissue_number": 3}}]
- results = compute_all_tissue_correlation(
+ results = compute_tissue_correlation(
primary_tissue_dict=primary_tissue_dict,
target_tissues_data=target_tissue_data,
corr_method="pearson")
@@ -464,3 +464,31 @@ class TestCorrelation(TestCase):
trait_symbol_dict, tissue_values_dict)
self.assertEqual(results, [expected_results])
+
+ def test_compute_correlation(self):
+ """Test that the new correlation function works the same as the original
+ from genenetwork1."""
+ for dbdata, userdata, expected in [
+ [[None, None, None, None, None, None, None, None, None, None],
+ [None, None, None, None, None, None, None, None, None, None],
+ (0.0, 0)],
+ [[None, None, None, None, None, None, None, None, None, 0],
+ [None, None, None, None, None, None, None, None, None, None],
+ (0.0, 0)],
+ [[None, None, None, None, None, None, None, None, None, 0],
+ [None, None, None, None, None, None, None, None, None, 0],
+ (0.0, 1)],
+ [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ (0, 10)],
+ [[9.87, 9.87, 9.87, 9.87, 9.87, 9.87, 9.87, 9.87, 9.87, 9.87],
+ [9.87, 9.87, 9.87, 9.87, 9.87, 9.87, 9.87, 9.87, 9.87, 9.87],
+ (0.9999999999999998, 10)],
+ [[9.3, 2.2, 5.4, 7.2, 6.4, 7.6, 3.8, 1.8, 8.4, 0.2],
+ [0.6, 3.97, 5.82, 8.21, 1.65, 4.55, 6.72, 9.5, 7.33, 2.34],
+ (-0.12720361919462056, 10)],
+ [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
+ [None, None, None, None, 2, None, None, 3, None, None],
+ (0.0, 2)]]:
+ with self.subTest(dbdata=dbdata, userdata=userdata):
+ self.assertEqual(compute_correlation(
+ dbdata, userdata), expected)
diff --git a/tests/unit/computations/test_heatmap.py b/tests/unit/computations/test_heatmap.py
new file mode 100644
index 0000000..650cb45
--- /dev/null
+++ b/tests/unit/computations/test_heatmap.py
@@ -0,0 +1,143 @@
+"""Module contains tests for gn3.computations.heatmap"""
+from unittest import TestCase
+from gn3.computations.heatmap import cluster_traits, export_trait_data
+
+strainlist = ["B6cC3-1", "BXD1", "BXD12", "BXD16", "BXD19", "BXD2"]
+trait_data = {
+ "mysqlid": 36688172,
+ "data": {
+ "B6cC3-1": {"strain_name": "B6cC3-1", "value": 7.51879, "variance": None, "ndata": None},
+ "BXD1": {"strain_name": "BXD1", "value": 7.77141, "variance": None, "ndata": None},
+ "BXD12": {"strain_name": "BXD12", "value": 8.39265, "variance": None, "ndata": None},
+ "BXD16": {"strain_name": "BXD16", "value": 8.17443, "variance": None, "ndata": None},
+ "BXD19": {"strain_name": "BXD19", "value": 8.30401, "variance": None, "ndata": None},
+ "BXD2": {"strain_name": "BXD2", "value": 7.80944, "variance": None, "ndata": None},
+ "BXD21": {"strain_name": "BXD21", "value": 8.93809, "variance": None, "ndata": None},
+ "BXD24": {"strain_name": "BXD24", "value": 7.99415, "variance": None, "ndata": None},
+ "BXD27": {"strain_name": "BXD27", "value": 8.12177, "variance": None, "ndata": None},
+ "BXD28": {"strain_name": "BXD28", "value": 7.67688, "variance": None, "ndata": None},
+ "BXD32": {"strain_name": "BXD32", "value": 7.79062, "variance": None, "ndata": None},
+ "BXD39": {"strain_name": "BXD39", "value": 8.27641, "variance": None, "ndata": None},
+ "BXD40": {"strain_name": "BXD40", "value": 8.18012, "variance": None, "ndata": None},
+ "BXD42": {"strain_name": "BXD42", "value": 7.82433, "variance": None, "ndata": None},
+ "BXD6": {"strain_name": "BXD6", "value": 8.09718, "variance": None, "ndata": None},
+ "BXH14": {"strain_name": "BXH14", "value": 7.97475, "variance": None, "ndata": None},
+ "BXH19": {"strain_name": "BXH19", "value": 7.67223, "variance": None, "ndata": None},
+ "BXH2": {"strain_name": "BXH2", "value": 7.93622, "variance": None, "ndata": None},
+ "BXH22": {"strain_name": "BXH22", "value": 7.43692, "variance": None, "ndata": None},
+ "BXH4": {"strain_name": "BXH4", "value": 7.96336, "variance": None, "ndata": None},
+ "BXH6": {"strain_name": "BXH6", "value": 7.75132, "variance": None, "ndata": None},
+ "BXH7": {"strain_name": "BXH7", "value": 8.12927, "variance": None, "ndata": None},
+ "BXH8": {"strain_name": "BXH8", "value": 6.77338, "variance": None, "ndata": None},
+ "BXH9": {"strain_name": "BXH9", "value": 8.03836, "variance": None, "ndata": None},
+ "C3H/HeJ": {"strain_name": "C3H/HeJ", "value": 7.42795, "variance": None, "ndata": None},
+ "C57BL/6J": {"strain_name": "C57BL/6J", "value": 7.50606, "variance": None, "ndata": None},
+ "DBA/2J": {"strain_name": "DBA/2J", "value": 7.72588, "variance": None, "ndata": None}}}
+
+class TestHeatmap(TestCase):
+ """Class for testing heatmap computation functions"""
+
+ def test_export_trait_data_dtype(self):
+ """
+ Test `export_trait_data` with different values for the `dtype` keyword
+ argument
+ """
+ for dtype, expected in [
+ ["val", (7.51879, 7.77141, 8.39265, 8.17443, 8.30401, 7.80944)],
+ ["var", (None, None, None, None, None, None)],
+ ["N", (None, None, None, None, None, None)],
+ ["all", (7.51879, 7.77141, 8.39265, 8.17443, 8.30401, 7.80944)]]:
+ with self.subTest(dtype=dtype):
+ self.assertEqual(
+ export_trait_data(trait_data, strainlist, dtype=dtype),
+ expected)
+
+ def test_export_trait_data_dtype_all_flags(self):
+ """
+ Test `export_trait_data` with different values for the `dtype` keyword
+ argument and the different flags set up
+ """
+ for dtype, vflag, nflag, expected in [
+ ["val", False, False,
+ (7.51879, 7.77141, 8.39265, 8.17443, 8.30401, 7.80944)],
+ ["val", False, True,
+ (7.51879, 7.77141, 8.39265, 8.17443, 8.30401, 7.80944)],
+ ["val", True, False,
+ (7.51879, 7.77141, 8.39265, 8.17443, 8.30401, 7.80944)],
+ ["val", True, True,
+ (7.51879, 7.77141, 8.39265, 8.17443, 8.30401, 7.80944)],
+ ["var", False, False, (None, None, None, None, None, None)],
+ ["var", False, True, (None, None, None, None, None, None)],
+ ["var", True, False, (None, None, None, None, None, None)],
+ ["var", True, True, (None, None, None, None, None, None)],
+ ["N", False, False, (None, None, None, None, None, None)],
+ ["N", False, True, (None, None, None, None, None, None)],
+ ["N", True, False, (None, None, None, None, None, None)],
+ ["N", True, True, (None, None, None, None, None, None)],
+ ["all", False, False,
+ (7.51879, 7.77141, 8.39265, 8.17443, 8.30401, 7.80944)],
+ ["all", False, True,
+ (7.51879, None, 7.77141, None, 8.39265, None, 8.17443, None,
+ 8.30401, None, 7.80944, None)],
+ ["all", True, False,
+ (7.51879, None, 7.77141, None, 8.39265, None, 8.17443, None,
+ 8.30401, None, 7.80944, None)],
+ ["all", True, True,
+ (7.51879, None, None, 7.77141, None, None, 8.39265, None, None,
+ 8.17443, None, None, 8.30401, None, None, 7.80944, None, None)]
+ ]:
+ with self.subTest(dtype=dtype, vflag=vflag, nflag=nflag):
+ self.assertEqual(
+ export_trait_data(
+ trait_data, strainlist, dtype=dtype, var_exists=vflag,
+ n_exists=nflag),
+ expected)
+
+ def test_cluster_traits(self):
+ """
+ Test that the clustering is working as expected.
+ """
+ traits_data_list = [
+ (7.51879, 7.77141, 8.39265, 8.17443, 8.30401, 7.80944),
+ (6.1427, 6.50588, 7.73705, 6.68328, 7.49293, 7.27398),
+ (8.4211, 8.30581, 9.24076, 8.51173, 9.18455, 8.36077),
+ (10.0904, 10.6509, 9.36716, 9.91202, 8.57444, 10.5731),
+ (10.188, 9.76652, 9.54813, 9.05074, 9.52319, 9.10505),
+ (6.74676, 7.01029, 7.54169, 6.48574, 7.01427, 7.26815),
+ (6.39359, 6.85321, 5.78337, 7.11141, 6.22101, 6.16544),
+ (6.84118, 7.08432, 7.59844, 7.08229, 7.26774, 7.24991),
+ (9.45215, 10.6943, 8.64719, 10.1592, 7.75044, 8.78615),
+ (7.04737, 6.87185, 7.58586, 6.92456, 6.84243, 7.36913)]
+ self.assertEqual(
+ cluster_traits(traits_data_list),
+ ((0.0, 0.20337048635536847, 0.16381088984330505, 1.7388553629398245,
+ 1.5025235756329178, 0.6952839500255574, 1.271661230252733,
+ 0.2100487290977544, 1.4699690641062024, 0.7934461515867415),
+ (0.20337048635536847, 0.0, 0.2198321044997198, 1.5753041735592204,
+ 1.4815755944537086, 0.26087293140686374, 1.6939790104301427,
+ 0.06024619831474998, 1.7430082449189215, 0.4497104244247795),
+ (0.16381088984330505, 0.2198321044997198, 0.0, 1.9073926868549234,
+ 1.0396738891139845, 0.5278328671176757, 1.6275069061182947,
+ 0.2636503792482082, 1.739617877037615, 0.7127042590637039),
+ (1.7388553629398245, 1.5753041735592204, 1.9073926868549234, 0.0,
+ 0.9936846292920328, 1.1169999189889366, 0.6007483980555253,
+ 1.430209221053372, 0.25879514152086425, 0.9313185954797953),
+ (1.5025235756329178, 1.4815755944537086, 1.0396738891139845,
+ 0.9936846292920328, 0.0, 1.027827186339337, 1.1441743109173244,
+ 1.4122477962364253, 0.8968250491499363, 1.1683723389247052),
+ (0.6952839500255574, 0.26087293140686374, 0.5278328671176757,
+ 1.1169999189889366, 1.027827186339337, 0.0, 1.8420471110023269,
+ 0.19179284676938602, 1.4875072385631605, 0.23451785425383564),
+ (1.271661230252733, 1.6939790104301427, 1.6275069061182947,
+ 0.6007483980555253, 1.1441743109173244, 1.8420471110023269, 0.0,
+ 1.6540234785929928, 0.2140799896286565, 1.7413442197913358),
+ (0.2100487290977544, 0.06024619831474998, 0.2636503792482082,
+ 1.430209221053372, 1.4122477962364253, 0.19179284676938602,
+ 1.6540234785929928, 0.0, 1.5225640692832796, 0.33370067057028485),
+ (1.4699690641062024, 1.7430082449189215, 1.739617877037615,
+ 0.25879514152086425, 0.8968250491499363, 1.4875072385631605,
+ 0.2140799896286565, 1.5225640692832796, 0.0, 1.3256191648260216),
+ (0.7934461515867415, 0.4497104244247795, 0.7127042590637039,
+ 0.9313185954797953, 1.1683723389247052, 0.23451785425383564,
+ 1.7413442197913358, 0.33370067057028485, 1.3256191648260216,
+ 0.0)))
diff --git a/tests/unit/computations/test_slink.py b/tests/unit/computations/test_slink.py
new file mode 100644
index 0000000..995393b
--- /dev/null
+++ b/tests/unit/computations/test_slink.py
@@ -0,0 +1,311 @@
+"""Module contains tests for slink"""
+from unittest import TestCase
+
+from gn3.computations.slink import slink
+from gn3.computations.slink import nearest
+from gn3.computations.slink import LengthError
+from gn3.computations.slink import MirrorError
+
+class TestSlink(TestCase):
+ """Class for testing slink functions"""
+
+ def test_nearest_expects_list_of_lists(self):
+ """Test that function only accepts a list of lists."""
+ # This might be better handled with type-hints and mypy
+ for item in [9, "some string", 5.432,
+ [1, 2, 3], ["test", 7.4]]:
+ with self.subTest(item=item):
+ with self.assertRaises(ValueError, msg="Expected list or tuple"):
+ nearest(item, 1, 1)
+
+ def test_nearest_does_not_allow_empty_lists(self):
+ """Test that function does not accept an empty list, or any of the child
+ lists to be empty."""
+ for lst in [[],
+ [[], []],
+ [[], [], []],
+ [[0, 1, 2], [], [1, 2, 0]]]:
+ with self.subTest(lst=lst):
+ with self.assertRaises(ValueError):
+ nearest(lst, 1, 1)
+
+ def test_nearest_expects_children_are_same_length_as_parent(self):
+ """Test that children lists are same length as parent list."""
+ for lst in [[[0, 1]],
+ [[0, 1, 2], [3, 4, 5]],
+ [[0, 1, 2, 3], [4, 5, 6], [7, 8, 9, 0]],
+ [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [1, 2, 3, 4, 5], [2, 3],
+ [3, 4, 5, 6, 7]]]:
+ with self.subTest(lst=lst):
+ with self.assertRaises(LengthError):
+ nearest(lst, 1, 1)
+
+ def test_nearest_expects_member_is_zero_distance_from_itself(self):
+ """Test that distance of a member from itself is zero"""
+ for lst in [[[1]],
+ [[1, 2], [3, 4]],
+ [1, 0, 0], [0, 0, 5], [0, 3, 4],
+ [0, 0, 0, 0], [0, 0, 3, 3], [0, 1, 2, 3], [0, 3, 2, 0]]:
+ with self.subTest(lst=lst):
+ with self.assertRaises(ValueError):
+ nearest(lst, 1, 1)
+
+ def test_nearest_expects_distance_atob_is_equal_to_distance_btoa(self):
+ """Test that the distance from member A to member B is the same as that
+ from member B to member A."""
+ for lst in [[[0, 1], [2, 0]],
+ [[0, 1, 2], [1, 0, 3], [9, 7, 0]],
+ [[0, 1, 2, 3], [7, 0, 2, 3], [2, 3, 0, 1], [8, 9, 5, 0]]]:
+ with self.subTest(lst=lst):
+ with self.assertRaises(MirrorError):
+ nearest(lst, 1, 1)
+
+ def test_nearest_expects_zero_or_positive_distances(self):
+ """Test that all distances are either zero, or greater than zero."""
+ # Based on:
+ # https://github.com/genenetwork/genenetwork1/blob/master/web/webqtl/heatmap/slink.py#L87-L89
+ for lst in [[[0, -1, 2, 3], [-1, 0, 3, 4], [2, 3, 0, 5], [3, 4, 5, 0]],
+ [[0, 1, -2, 3], [1, 0, 3, 4], [-2, 3, 0, 5], [3, 4, 5, 0]],
+ [[0, 1, 2, 3], [1, 0, -3, 4], [2, -3, 0, 5], [3, 4, 5, 0]],
+ [[0, 1, 2, -3], [1, 0, 3, 4], [2, 3, 0, 5], [-3, 4, 5, 0]],
+ [[0, 1, 2, 3], [1, 0, 3, -4], [2, 3, 0, 5], [3, -4, 5, 0]],
+ [[0, 1, 2, 3], [1, 0, 3, 4], [2, 3, 0, -5], [3, 4, -5, 0]]]:
+ with self.subTest(lst=lst):
+ with self.assertRaises(ValueError, msg="Distances should be positive."):
+ nearest(lst, 1, 1)
+
+ def test_nearest_returns_shortest_distance_given_coordinates_to_both_group_members(self):
+ """Test that the shortest distance is returned."""
+ # This test is named wrong - at least I think it is, from the expected results
+ # This tests distance when both `i`, and `j` are integers
+ # We still need to add tests for when (either one/both) (is/are) not (an) integer(s)
+ # https://github.com/genenetwork/genenetwork1/blob/master/web/webqtl/heatmap/slink.py#L39-L40
+ for lst, i, j, expected in [
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]],
+ 0, 0, 0],
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]],
+ 0, 1, 9],
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]],
+ 0, 2, 3],
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]],
+ 0, 3, 6],
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]],
+ 0, 4, 11],
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]],
+ 1, 0, 9],
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]],
+ 1, 1, 0],
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]],
+ 1, 2, 7],
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]],
+ 1, 3, 5],
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]],
+ 1, 4, 10],
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]],
+ 2, 0, 3],
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]],
+ 2, 1, 7],
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]],
+ 2, 2, 0],
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]],
+ 2, 3, 9],
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]],
+ 2, 4, 2],
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]],
+ 3, 0, 6],
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]],
+ 3, 1, 5],
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]],
+ 3, 2, 9],
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]],
+ 3, 3, 0],
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]],
+ 3, 4, 8],
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]],
+ 4, 0, 11],
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]],
+ 4, 1, 10],
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]],
+ 4, 2, 2],
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]],
+ 4, 3, 8],
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]],
+ 4, 4, 0],
+ [[[0, 9, 5.5, 6, 11], [9, 0, 7, 5, 10], [5.5, 7, 0, 9, 2],
+ [6, 5, 9, 0, 3], [11, 10, 2, 3, 0]],
+ 0, 0, 0],
+ [[[0, 9, 5.5, 6, 11], [9, 0, 7, 5, 10], [5.5, 7, 0, 9, 2],
+ [6, 5, 9, 0, 3], [11, 10, 2, 3, 0]],
+ 0, 1, 9],
+ [[[0, 9, 5.5, 6, 11], [9, 0, 7, 5, 10], [5.5, 7, 0, 9, 2],
+ [6, 5, 9, 0, 3], [11, 10, 2, 3, 0]],
+ 0, 2, 5.5],
+ [[[0, 9, 5.5, 6, 11], [9, 0, 7, 5, 10], [5.5, 7, 0, 9, 2],
+ [6, 5, 9, 0, 3], [11, 10, 2, 3, 0]],
+ 0, 3, 6],
+ [[[0, 9, 5.5, 6, 11], [9, 0, 7, 5, 10], [5.5, 7, 0, 9, 2],
+ [6, 5, 9, 0, 3], [11, 10, 2, 3, 0]],
+ 0, 4, 11],
+ [[[0, 9, 5.5, 6, 11], [9, 0, 7, 5, 10], [5.5, 7, 0, 9, 2],
+ [6, 5, 9, 0, 3], [11, 10, 2, 3, 0]],
+ 1, 0, 9],
+ [[[0, 9, 5.5, 6, 11], [9, 0, 7, 5, 10], [5.5, 7, 0, 9, 2],
+ [6, 5, 9, 0, 3], [11, 10, 2, 3, 0]],
+ 1, 1, 0],
+ [[[0, 9, 5.5, 6, 11], [9, 0, 7, 5, 10], [5.5, 7, 0, 9, 2],
+ [6, 5, 9, 0, 3], [11, 10, 2, 3, 0]],
+ 1, 2, 7],
+ [[[0, 9, 5.5, 6, 11], [9, 0, 7, 5, 10], [5.5, 7, 0, 9, 2],
+ [6, 5, 9, 0, 3], [11, 10, 2, 3, 0]],
+ 1, 3, 5],
+ [[[0, 9, 5.5, 6, 11], [9, 0, 7, 5, 10], [5.5, 7, 0, 9, 2],
+ [6, 5, 9, 0, 3], [11, 10, 2, 3, 0]],
+ 1, 4, 10],
+ [[[0, 9, 5.5, 6, 11], [9, 0, 7, 5, 10], [5.5, 7, 0, 9, 2],
+ [6, 5, 9, 0, 3], [11, 10, 2, 3, 0]],
+ 2, 0, 5.5],
+ [[[0, 9, 5.5, 6, 11], [9, 0, 7, 5, 10], [5.5, 7, 0, 9, 2],
+ [6, 5, 9, 0, 3], [11, 10, 2, 3, 0]],
+ 2, 1, 7],
+ [[[0, 9, 5.5, 6, 11], [9, 0, 7, 5, 10], [5.5, 7, 0, 9, 2],
+ [6, 5, 9, 0, 3], [11, 10, 2, 3, 0]],
+ 2, 2, 0],
+ [[[0, 9, 5.5, 6, 11], [9, 0, 7, 5, 10], [5.5, 7, 0, 9, 2],
+ [6, 5, 9, 0, 3], [11, 10, 2, 3, 0]],
+ 2, 3, 9],
+ [[[0, 9, 5.5, 6, 11], [9, 0, 7, 5, 10], [5.5, 7, 0, 9, 2],
+ [6, 5, 9, 0, 3], [11, 10, 2, 3, 0]],
+ 2, 4, 2],
+ [[[0, 9, 5.5, 6, 11], [9, 0, 7, 5, 10], [5.5, 7, 0, 9, 2],
+ [6, 5, 9, 0, 3], [11, 10, 2, 3, 0]],
+ 3, 0, 6],
+ [[[0, 9, 5.5, 6, 11], [9, 0, 7, 5, 10], [5.5, 7, 0, 9, 2],
+ [6, 5, 9, 0, 3], [11, 10, 2, 3, 0]],
+ 3, 1, 5],
+ [[[0, 9, 5.5, 6, 11], [9, 0, 7, 5, 10], [5.5, 7, 0, 9, 2],
+ [6, 5, 9, 0, 3], [11, 10, 2, 3, 0]],
+ 3, 2, 9],
+ [[[0, 9, 5.5, 6, 11], [9, 0, 7, 5, 10], [5.5, 7, 0, 9, 2],
+ [6, 5, 9, 0, 3], [11, 10, 2, 3, 0]],
+ 3, 3, 0],
+ [[[0, 9, 5.5, 6, 11], [9, 0, 7, 5, 10], [5.5, 7, 0, 9, 2],
+ [6, 5, 9, 0, 3], [11, 10, 2, 3, 0]],
+ 3, 4, 3],
+ [[[0, 9, 5.5, 6, 11], [9, 0, 7, 5, 10], [5.5, 7, 0, 9, 2],
+ [6, 5, 9, 0, 3], [11, 10, 2, 3, 0]],
+ 4, 0, 11],
+ [[[0, 9, 5.5, 6, 11], [9, 0, 7, 5, 10], [5.5, 7, 0, 9, 2],
+ [6, 5, 9, 0, 3], [11, 10, 2, 3, 0]],
+ 4, 1, 10],
+ [[[0, 9, 5.5, 6, 11], [9, 0, 7, 5, 10], [5.5, 7, 0, 9, 2],
+ [6, 5, 9, 0, 3], [11, 10, 2, 3, 0]],
+ 4, 2, 2],
+ [[[0, 9, 5.5, 6, 11], [9, 0, 7, 5, 10], [5.5, 7, 0, 9, 2],
+ [6, 5, 9, 0, 3], [11, 10, 2, 3, 0]],
+ 4, 3, 3],
+ [[[0, 9, 5.5, 6, 11], [9, 0, 7, 5, 10], [5.5, 7, 0, 9, 2],
+ [6, 5, 9, 0, 3], [11, 10, 2, 3, 0]],
+ 4, 4, 0]]:
+ with self.subTest(lst=lst):
+ self.assertEqual(nearest(lst, i, j), expected)
+
+ def test_nearest_gives_shortest_distance_between_list_of_members_and_member(self):
+ """Test that the shortest distance is returned."""
+ for members_distances, members_list, member_coordinate, expected_distance in [
+ [[[0, 9, 3], [9, 0, 7], [3, 7, 0]], (0, 2, 3), 1, 7],
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]], [0, 1, 2, 3, 4], 3, 0],
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]], [0, 1, 2, 4], 3, 5],
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]], [0, 2, 4], 3, 6],
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]], [2, 4], 3, 9]]:
+ with self.subTest(
+ members_distances=members_distances,
+ members_list=members_list,
+ member_coordinate=member_coordinate,
+ expected_distance=expected_distance):
+ self.assertEqual(
+ nearest(
+ members_distances, members_list, member_coordinate),
+ expected_distance)
+ self.assertEqual(
+ nearest(
+ members_distances, member_coordinate, members_list),
+ expected_distance)
+
+ def test_nearest_returns_shortest_distance_given_two_lists_of_members(self):
+ """Test that the shortest distance is returned."""
+ for members_distances, members_list, member_list2, expected_distance in [
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]],
+ [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], 0],
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]],
+ [0, 1], [3, 4], 6],
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]],
+ [0, 1], [2, 3, 4], 3],
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8], [11, 10, 2, 8, 0]],
+ [0, 2], [3, 4], 6]]:
+ with self.subTest(
+ members_distances=members_distances,
+ members_list=members_list,
+ member_list2=member_list2,
+ expected_distance=expected_distance):
+ self.assertEqual(
+ nearest(
+ members_distances, members_list, member_list2),
+ expected_distance)
+ self.assertEqual(
+ nearest(
+ members_distances, member_list2, members_list),
+ expected_distance)
+
+ def test_slink_wrong_data_returns_empty_list(self):
+ """Test that empty list is returned for wrong data."""
+ for data in [1, "test", [], 2.945, nearest, [0]]:
+ with self.subTest(data=data):
+ self.assertEqual(slink(data), [])
+
+ def test_slink_with_data(self):
+ """Test slink with example data, and expected results for each data
+ sample."""
+ for data, expected in [
+ [[[0, 9], [9, 0]], [0, 1, 9]],
+ [[[0, 9, 3], [9, 0, 7], [3, 7, 0]], [(0, 2, 3), 1, 7]],
+ [[[0, 9, 3, 6], [9, 0, 7, 5], [3, 7, 0, 9], [6, 5, 9, 0]],
+ [(0, 2, 3), (1, 3, 5), 6]],
+ [[[0, 9, 3, 6, 11], [9, 0, 7, 5, 10], [3, 7, 0, 9, 2],
+ [6, 5, 9, 0, 8],
+ [11, 10, 2, 8, 0]],
+ [(0, (2, 4, 2), 3), (1, 3, 5), 6]]]:
+ with self.subTest(data=data):
+ self.assertEqual(slink(data), expected)
diff --git a/tests/unit/db/test_datasets.py b/tests/unit/db/test_datasets.py
new file mode 100644
index 0000000..38de0e2
--- /dev/null
+++ b/tests/unit/db/test_datasets.py
@@ -0,0 +1,133 @@
+"""Tests for gn3/db/datasets.py"""
+
+from unittest import mock, TestCase
+from gn3.db.datasets import (
+ retrieve_dataset_name,
+ retrieve_riset_fields,
+ retrieve_geno_riset_fields,
+ retrieve_publish_riset_fields,
+ retrieve_probeset_riset_fields)
+
+class TestDatasetsDBFunctions(TestCase):
+ """Test cases for datasets functions."""
+
+ def test_retrieve_dataset_name(self):
+ """Test that the function is called correctly."""
+ for trait_type, thresh, trait_name, dataset_name, columns, table in [
+ ["ProbeSet", 9, "probesetTraitName", "probesetDatasetName",
+ "Id, Name, FullName, ShortName, DataScale", "ProbeSetFreeze"],
+ ["Geno", 3, "genoTraitName", "genoDatasetName",
+ "Id, Name, FullName, ShortName", "GenoFreeze"],
+ ["Publish", 6, "publishTraitName", "publishDatasetName",
+ "Id, Name, FullName, ShortName", "PublishFreeze"],
+ ["Temp", 4, "tempTraitName", "tempTraitName",
+ "Id, Name, FullName, ShortName", "TempFreeze"]]:
+ db_mock = mock.MagicMock()
+ with self.subTest(trait_type=trait_type):
+ with db_mock.cursor() as cursor:
+ cursor.fetchone.return_value = {}
+ self.assertEqual(
+ retrieve_dataset_name(
+ trait_type, thresh, trait_name, dataset_name, db_mock),
+ {})
+ cursor.execute.assert_called_once_with(
+ "SELECT {cols} "
+ "FROM {table} "
+ "WHERE public > %(threshold)s AND "
+ "(Name = %(name)s "
+ "OR FullName = %(name)s "
+ "OR ShortName = %(name)s)".format(
+ table=table, cols=columns),
+ {"threshold": thresh, "name": dataset_name})
+
+ def test_retrieve_probeset_riset_fields(self):
+ """
+ Test that the `riset` and `riset_id` fields are retrieved appropriately
+ for the 'ProbeSet' trait type.
+ """
+ for trait_name, expected in [
+ ["testProbeSetName", {}]]:
+ db_mock = mock.MagicMock()
+ with self.subTest(trait_name=trait_name, expected=expected):
+ with db_mock.cursor() as cursor:
+ cursor.execute.return_value = ()
+ self.assertEqual(
+ retrieve_probeset_riset_fields(trait_name, db_mock),
+ expected)
+ cursor.execute.assert_called_once_with(
+ (
+ "SELECT InbredSet.Name, InbredSet.Id"
+ " FROM InbredSet, ProbeSetFreeze, ProbeFreeze"
+ " WHERE ProbeFreeze.InbredSetId = InbredSet.Id"
+ " AND ProbeFreeze.Id = ProbeSetFreeze.ProbeFreezeId"
+ " AND ProbeSetFreeze.Name = %(name)s"),
+ {"name": trait_name})
+
+ def test_retrieve_riset_fields(self):
+ """
+ Test that the riset fields are set up correctly for the different trait
+ types.
+ """
+ for trait_type, trait_name, dataset_info, expected in [
+ ["Publish", "pubTraitName01", {"dataset_name": "pubDBName01"},
+ {"dataset_name": "pubDBName01", "riset": ""}],
+ ["ProbeSet", "prbTraitName01", {"dataset_name": "prbDBName01"},
+ {"dataset_name": "prbDBName01", "riset": ""}],
+ ["Geno", "genoTraitName01", {"dataset_name": "genoDBName01"},
+ {"dataset_name": "genoDBName01", "riset": ""}],
+ ["Temp", "tempTraitName01", {}, {"riset": ""}],
+ ]:
+ db_mock = mock.MagicMock()
+ with self.subTest(
+ trait_type=trait_type, trait_name=trait_name,
+ dataset_info=dataset_info):
+ with db_mock.cursor() as cursor:
+ cursor.execute.return_value = ("riset_name", 0)
+ self.assertEqual(
+ retrieve_riset_fields(
+ trait_type, trait_name, dataset_info, db_mock),
+ expected)
+
+ def test_retrieve_publish_riset_fields(self):
+ """
+ Test that the `riset` and `riset_id` fields are retrieved appropriately
+ for the 'Publish' trait type.
+ """
+ for trait_name, expected in [
+ ["testPublishName", {}]]:
+ db_mock = mock.MagicMock()
+ with self.subTest(trait_name=trait_name, expected=expected):
+ with db_mock.cursor() as cursor:
+ cursor.execute.return_value = ()
+ self.assertEqual(
+ retrieve_publish_riset_fields(trait_name, db_mock),
+ expected)
+ cursor.execute.assert_called_once_with(
+ (
+ "SELECT InbredSet.Name, InbredSet.Id"
+ " FROM InbredSet, PublishFreeze"
+ " WHERE PublishFreeze.InbredSetId = InbredSet.Id"
+ " AND PublishFreeze.Name = %(name)s"),
+ {"name": trait_name})
+
+ def test_retrieve_geno_riset_fields(self):
+ """
+ Test that the `riset` and `riset_id` fields are retrieved appropriately
+ for the 'Geno' trait type.
+ """
+ for trait_name, expected in [
+ ["testGenoName", {}]]:
+ db_mock = mock.MagicMock()
+ with self.subTest(trait_name=trait_name, expected=expected):
+ with db_mock.cursor() as cursor:
+ cursor.execute.return_value = ()
+ self.assertEqual(
+ retrieve_geno_riset_fields(trait_name, db_mock),
+ expected)
+ cursor.execute.assert_called_once_with(
+ (
+ "SELECT InbredSet.Name, InbredSet.Id"
+ " FROM InbredSet, GenoFreeze"
+ " WHERE GenoFreeze.InbredSetId = InbredSet.Id"
+ " AND GenoFreeze.Name = %(name)s"),
+ {"name": trait_name})
diff --git a/tests/unit/db/test_traits.py b/tests/unit/db/test_traits.py
new file mode 100644
index 0000000..ee98893
--- /dev/null
+++ b/tests/unit/db/test_traits.py
@@ -0,0 +1,224 @@
+"""Tests for gn3/db/traits.py"""
+from unittest import mock, TestCase
+from gn3.db.traits import (
+ build_trait_name,
+ set_haveinfo_field,
+ update_sample_data,
+ retrieve_trait_info,
+ set_confidential_field,
+ set_homologene_id_field,
+ retrieve_geno_trait_info,
+ retrieve_temp_trait_info,
+ retrieve_publish_trait_info,
+ retrieve_probeset_trait_info)
+
+class TestTraitsDBFunctions(TestCase):
+ "Test cases for traits functions"
+
+ def test_retrieve_publish_trait_info(self):
+ """Test retrieval of type `Publish` traits."""
+ db_mock = mock.MagicMock()
+ with db_mock.cursor() as cursor:
+ cursor.fetchone.return_value = tuple()
+ trait_source = {
+ "trait_name": "PublishTraitName", "trait_dataset_id": 1}
+ self.assertEqual(
+ retrieve_publish_trait_info(trait_source, db_mock), {})
+ cursor.execute.assert_called_once_with(
+ ("SELECT "
+ "PublishXRef.Id, Publication.PubMed_ID,"
+ " Phenotype.Pre_publication_description,"
+ " Phenotype.Post_publication_description,"
+ " Phenotype.Original_description,"
+ " Phenotype.Pre_publication_abbreviation,"
+ " Phenotype.Post_publication_abbreviation,"
+ " Phenotype.Lab_code, Phenotype.Submitter, Phenotype.Owner,"
+ " Phenotype.Authorized_Users,"
+ " CAST(Publication.Authors AS BINARY),"
+ " Publication.Title, Publication.Abstract,"
+ " Publication.Journal,"
+ " Publication.Volume, Publication.Pages, Publication.Month,"
+ " Publication.Year, PublishXRef.Sequence, Phenotype.Units,"
+ " PublishXRef.comments"
+ " FROM"
+ " PublishXRef, Publication, Phenotype, PublishFreeze"
+ " WHERE"
+ " PublishXRef.Id = %(trait_name)s"
+ " AND Phenotype.Id = PublishXRef.PhenotypeId"
+ " AND Publication.Id = PublishXRef.PublicationId"
+ " AND PublishXRef.InbredSetId = PublishFreeze.InbredSetId"
+ " AND PublishFreeze.Id =%(trait_dataset_id)s"),
+ trait_source)
+
+ def test_retrieve_probeset_trait_info(self):
+ """Test retrieval of type `Probeset` traits."""
+ db_mock = mock.MagicMock()
+ with db_mock.cursor() as cursor:
+ cursor.fetchone.return_value = tuple()
+ trait_source = {
+ "trait_name": "ProbeSetTraitName",
+ "trait_dataset_name": "ProbeSetDatasetTraitName"}
+ self.assertEqual(
+ retrieve_probeset_trait_info(trait_source, db_mock), {})
+ cursor.execute.assert_called_once_with(
+ (
+ "SELECT "
+ "ProbeSet.name, ProbeSet.symbol, ProbeSet.description, "
+ "ProbeSet.probe_target_description, ProbeSet.chr, "
+ "ProbeSet.mb, ProbeSet.alias, ProbeSet.geneid, "
+ "ProbeSet.genbankid, ProbeSet.unigeneid, ProbeSet.omim, "
+ "ProbeSet.refseq_transcriptid, ProbeSet.blatseq, "
+ "ProbeSet.targetseq, ProbeSet.chipid, ProbeSet.comments, "
+ "ProbeSet.strand_probe, ProbeSet.strand_gene, "
+ "ProbeSet.probe_set_target_region, ProbeSet.proteinid, "
+ "ProbeSet.probe_set_specificity, "
+ "ProbeSet.probe_set_blat_score, "
+ "ProbeSet.probe_set_blat_mb_start, "
+ "ProbeSet.probe_set_blat_mb_end, "
+ "ProbeSet.probe_set_strand, ProbeSet.probe_set_note_by_rw, "
+ "ProbeSet.flag "
+ "FROM "
+ "ProbeSet, ProbeSetFreeze, ProbeSetXRef "
+ "WHERE "
+ "ProbeSetXRef.ProbeSetFreezeId = ProbeSetFreeze.Id "
+ "AND ProbeSetXRef.ProbeSetId = ProbeSet.Id "
+ "AND ProbeSetFreeze.Name = %(trait_dataset_name)s "
+ "AND ProbeSet.Name = %(trait_name)s"), trait_source)
+
+ def test_retrieve_geno_trait_info(self):
+ """Test retrieval of type `Geno` traits."""
+ db_mock = mock.MagicMock()
+ with db_mock.cursor() as cursor:
+ cursor.fetchone.return_value = tuple()
+ trait_source = {
+ "trait_name": "GenoTraitName",
+ "trait_dataset_name": "GenoDatasetTraitName"}
+ self.assertEqual(
+ retrieve_geno_trait_info(trait_source, db_mock), {})
+ cursor.execute.assert_called_once_with(
+ (
+ "SELECT "
+ "Geno.name, Geno.chr, Geno.mb, Geno.source2, Geno.sequence "
+ "FROM "
+ "Geno, GenoFreeze, GenoXRef "
+ "WHERE "
+ "GenoXRef.GenoFreezeId = GenoFreeze.Id "
+ "AND GenoXRef.GenoId = Geno.Id "
+ "AND GenoFreeze.Name = %(trait_dataset_name)s "
+ "AND Geno.Name = %(trait_name)s"),
+ trait_source)
+
+ def test_retrieve_temp_trait_info(self):
+ """Test retrieval of type `Temp` traits."""
+ db_mock = mock.MagicMock()
+ with db_mock.cursor() as cursor:
+ cursor.fetchone.return_value = tuple()
+ trait_source = {"trait_name": "TempTraitName"}
+ self.assertEqual(
+ retrieve_temp_trait_info(trait_source, db_mock), {})
+ cursor.execute.assert_called_once_with(
+ "SELECT name, description FROM Temp WHERE Name = %(trait_name)s",
+ trait_source)
+
+ def test_build_trait_name_with_good_fullnames(self):
+ """
+ Check that the name is built correctly.
+ """
+ for fullname, expected in [
+ ["testdb::testname",
+ {"db": {"dataset_name": "testdb", "dataset_type": "ProbeSet"},
+ "trait_name": "testname", "cellid": "",
+ "trait_fullname": "testdb::testname"}],
+ ["testdb::testname::testcell",
+ {"db": {"dataset_name": "testdb", "dataset_type": "ProbeSet"},
+ "trait_name": "testname", "cellid": "testcell",
+ "trait_fullname": "testdb::testname::testcell"}]]:
+ with self.subTest(fullname=fullname):
+ self.assertEqual(build_trait_name(fullname), expected)
+
+ def test_build_trait_name_with_bad_fullnames(self):
+ """
+ Check that an exception is raised if the full name format is wrong.
+ """
+ for fullname in ["", "test", "test:test"]:
+ with self.subTest(fullname=fullname):
+ with self.assertRaises(AssertionError, msg="Name format error"):
+ build_trait_name(fullname)
+
+ def test_retrieve_trait_info(self):
+ """Test that information on traits is retrieved as appropriate."""
+ for threshold, trait_fullname, expected in [
+ [9, "pubDb::PublishTraitName::pubCell", {"haveinfo": 0}],
+ [5, "prbDb::ProbeSetTraitName::prbCell", {"haveinfo": 0}],
+ [12, "genDb::GenoTraitName", {"haveinfo": 0}],
+ [6, "tmpDb::TempTraitName", {"haveinfo": 0}]]:
+ db_mock = mock.MagicMock()
+ with self.subTest(trait_fullname=trait_fullname):
+ with db_mock.cursor() as cursor:
+ cursor.fetchone.return_value = tuple()
+ self.assertEqual(
+ retrieve_trait_info(
+ threshold, trait_fullname, db_mock),
+ expected)
+
+ def test_update_sample_data(self):
+ """Test that the SQL queries when calling update_sample_data are called with
+ the right calls.
+
+ """
+ db_mock = mock.MagicMock()
+
+ STRAIN_ID_SQL: str = "UPDATE Strain SET Name = %s WHERE Id = %s"
+ PUBLISH_DATA_SQL: str = ("UPDATE PublishData SET value = %s "
+ "WHERE StrainId = %s AND Id = %s")
+ PUBLISH_SE_SQL: str = ("UPDATE PublishSE SET error = %s "
+ "WHERE StrainId = %s AND DataId = %s")
+ N_STRAIN_SQL: str = ("UPDATE NStrain SET count = %s "
+ "WHERE StrainId = %s AND DataId = %s")
+
+ with db_mock.cursor() as cursor:
+ type(cursor).rowcount = 1
+ self.assertEqual(update_sample_data(
+ conn=db_mock, strain_name="BXD11",
+ strain_id=10, publish_data_id=8967049,
+ value=18.7, error=2.3, count=2),
+ (1, 1, 1, 1))
+ cursor.execute.assert_has_calls(
+ [mock.call(STRAIN_ID_SQL, ('BXD11', 10)),
+ mock.call(PUBLISH_DATA_SQL, (18.7, 10, 8967049)),
+ mock.call(PUBLISH_SE_SQL, (2.3, 10, 8967049)),
+ mock.call(N_STRAIN_SQL, (2, 10, 8967049))]
+ )
+
+ def test_set_haveinfo_field(self):
+ """Test that the `haveinfo` field is set up correctly"""
+ for trait_info, expected in [
+ [{}, {"haveinfo": 0}],
+ [{"k1": "v1"}, {"k1": "v1", "haveinfo": 1}]]:
+ with self.subTest(trait_info=trait_info, expected=expected):
+ self.assertEqual(set_haveinfo_field(trait_info), expected)
+
+ def test_set_homologene_id_field(self):
+ """Test that the `homologene_id` field is set up correctly"""
+ for trait_type, trait_info, expected in [
+ ["Publish", {}, {"homologeneid": None}],
+ ["ProbeSet", {}, {"homologeneid": None}],
+ ["Geno", {}, {"homologeneid": None}],
+ ["Temp", {}, {"homologeneid": None}]]:
+ db_mock = mock.MagicMock()
+ with self.subTest(trait_info=trait_info, expected=expected):
+ with db_mock.cursor() as cursor:
+ cursor.fetchone.return_value = ()
+ self.assertEqual(
+ set_homologene_id_field(trait_type, trait_info, db_mock), expected)
+
+ def test_set_confidential_field(self):
+ """Test that the `confidential` field is set up correctly"""
+ for trait_type, trait_info, expected in [
+ ["Publish", {}, {"confidential": 0}],
+ ["ProbeSet", {}, {}],
+ ["Geno", {}, {}],
+ ["Temp", {}, {}]]:
+ with self.subTest(trait_info=trait_info, expected=expected):
+ self.assertEqual(
+ set_confidential_field(trait_type, trait_info), expected)