about summary refs log tree commit diff
path: root/wqflask/tests/unit
diff options
context:
space:
mode:
authorArthur Centeno2021-10-25 21:04:23 +0000
committerArthur Centeno2021-10-25 21:04:23 +0000
commit499a80f138030c4de1629c043c8f9401a99894ea (patch)
tree449dcae965d13f966fb6d52625fbc86661c8c6a0 /wqflask/tests/unit
parent6151faa9ea67af4bf4ea95fb681a9dc4319474b6 (diff)
parent700802303e5e8221a9d591ba985d6607aa61e1ce (diff)
downloadgenenetwork2-499a80f138030c4de1629c043c8f9401a99894ea.tar.gz
Merge github.com:genenetwork/genenetwork2 into acenteno
Diffstat (limited to 'wqflask/tests/unit')
-rw-r--r--wqflask/tests/unit/__init__.py0
-rw-r--r--wqflask/tests/unit/base/__init__.py0
-rw-r--r--wqflask/tests/unit/base/data.py110
-rw-r--r--wqflask/tests/unit/base/test_data_set.py178
-rw-r--r--wqflask/tests/unit/base/test_general_object.py40
-rw-r--r--wqflask/tests/unit/base/test_species.py116
-rw-r--r--wqflask/tests/unit/base/test_trait.py241
-rw-r--r--wqflask/tests/unit/base/test_webqtl_case_data.py40
-rw-r--r--wqflask/tests/unit/utility/__init__.py0
-rw-r--r--wqflask/tests/unit/utility/test_authentication_tools.py190
-rw-r--r--wqflask/tests/unit/utility/test_chunks.py20
-rw-r--r--wqflask/tests/unit/utility/test_corestats.py55
-rw-r--r--wqflask/tests/unit/utility/test_corr_result_helpers.py32
-rw-r--r--wqflask/tests/unit/utility/test_formatting.py33
-rw-r--r--wqflask/tests/unit/utility/test_hmac.py51
-rw-r--r--wqflask/tests/unit/utility/test_type_checking.py54
-rw-r--r--wqflask/tests/unit/wqflask/__init__.py0
-rw-r--r--wqflask/tests/unit/wqflask/api/__init__.py0
-rw-r--r--wqflask/tests/unit/wqflask/api/test_correlation.py153
-rw-r--r--wqflask/tests/unit/wqflask/api/test_gen_menu.py423
-rw-r--r--wqflask/tests/unit/wqflask/api/test_mapping.py108
-rw-r--r--wqflask/tests/unit/wqflask/api/test_markdown_routes.py54
-rw-r--r--wqflask/tests/unit/wqflask/correlation/__init__.py0
-rw-r--r--wqflask/tests/unit/wqflask/correlation/test_correlation_functions.py40
-rw-r--r--wqflask/tests/unit/wqflask/correlation/test_correlation_gn3.py14
-rw-r--r--wqflask/tests/unit/wqflask/correlation/test_show_corr_results.py98
-rw-r--r--wqflask/tests/unit/wqflask/marker_regression/__init__.py0
-rw-r--r--wqflask/tests/unit/wqflask/marker_regression/test_display_mapping_results.py159
-rw-r--r--wqflask/tests/unit/wqflask/marker_regression/test_gemma_mapping.py188
-rw-r--r--wqflask/tests/unit/wqflask/marker_regression/test_plink_mapping.py86
-rw-r--r--wqflask/tests/unit/wqflask/marker_regression/test_qtlreaper_mapping.py24
-rw-r--r--wqflask/tests/unit/wqflask/marker_regression/test_rqtl_mapping.py43
-rw-r--r--wqflask/tests/unit/wqflask/marker_regression/test_run_mapping.py287
-rw-r--r--wqflask/tests/unit/wqflask/show_trait/__init__.py0
-rw-r--r--wqflask/tests/unit/wqflask/show_trait/test_export_trait_data.py212
-rw-r--r--wqflask/tests/unit/wqflask/snp_browser/__init__.py0
-rw-r--r--wqflask/tests/unit/wqflask/snp_browser/test_snp_browser.py105
-rw-r--r--wqflask/tests/unit/wqflask/test_collect.py75
-rw-r--r--wqflask/tests/unit/wqflask/test_pbkdf2.py61
-rw-r--r--wqflask/tests/unit/wqflask/test_resource_manager.py94
-rw-r--r--wqflask/tests/unit/wqflask/test_server_side.py34
-rw-r--r--wqflask/tests/unit/wqflask/test_user_login.py21
-rw-r--r--wqflask/tests/unit/wqflask/test_user_session.py15
-rw-r--r--wqflask/tests/unit/wqflask/wgcna/__init__.py0
-rw-r--r--wqflask/tests/unit/wqflask/wgcna/test_wgcna.py50
45 files changed, 3504 insertions, 0 deletions
diff --git a/wqflask/tests/unit/__init__.py b/wqflask/tests/unit/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/wqflask/tests/unit/__init__.py
diff --git a/wqflask/tests/unit/base/__init__.py b/wqflask/tests/unit/base/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/wqflask/tests/unit/base/__init__.py
diff --git a/wqflask/tests/unit/base/data.py b/wqflask/tests/unit/base/data.py
new file mode 100644
index 00000000..06a5a989
--- /dev/null
+++ b/wqflask/tests/unit/base/data.py
@@ -0,0 +1,110 @@
+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"
+        ]
+      ]
+    }
+  }
+}
+"""
diff --git a/wqflask/tests/unit/base/test_data_set.py b/wqflask/tests/unit/base/test_data_set.py
new file mode 100644
index 00000000..66ad361d
--- /dev/null
+++ b/wqflask/tests/unit/base/test_data_set.py
@@ -0,0 +1,178 @@
+"""Tests for wqflask/base/data_set.py"""
+
+import unittest
+from unittest import mock
+
+from wqflask import app
+from .data import gen_menu_json
+from base.data_set import DatasetType
+
+
+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()
+            redis_mock.get.return_value = self.test_dataset
+            self.assertEqual(DatasetType(redis_mock)
+                             ("All Phenotypes"), "Publish")
+            redis_mock.get.assert_called_once_with("dataset_structure")
+
+    @mock.patch('base.data_set.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()
+            redis_mock.get.return_value = None
+            data_set = DatasetType(redis_mock)
+            self.assertEqual(data_set("BXDGeno"), "Geno")
+            self.assertEqual(data_set("BXDPublish"), "Publish")
+            self.assertEqual(data_set("HLC_0311"), "ProbeSet")
+
+            redis_mock.set.assert_called_once_with(
+                "dataset_structure",
+                ('{"HLC_0311": "ProbeSet", '
+                 '"HLCPublish": "Publish", '
+                 '"BXDGeno": "Geno", '
+                 '"HC_M2_0606_P": "ProbeSet", '
+                 '"BXDPublish": "Publish"}'))
+
+    @mock.patch('base.data_set.g')
+    def test_set_dataset_key_mrna(self, db_mock):
+        with app.app_context():
+            db_mock.db.execute.return_value.fetchone.return_value = [1, 2, 3]
+            redis_mock = mock.Mock()
+            redis_mock.get.return_value = self.test_dataset
+            data_set = DatasetType(redis_mock)
+            data_set.set_dataset_key("mrna_expr", "Test")
+            self.assertEqual(data_set("Test"), "ProbeSet")
+            redis_mock.set.assert_called_once_with(
+                "dataset_structure",
+                ('{"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", '
+                 '"Test": "ProbeSet"}'))
+            db_mock.db.execute.assert_called_once_with(
+                ("SELECT ProbeSetFreeze.Id FROM ProbeSetFreeze "
+                 + "WHERE ProbeSetFreeze.Name = \"Test\" ")
+            )
+
+    @mock.patch('base.data_set.g')
+    def test_set_dataset_key_pheno(self, db_mock):
+        with app.app_context():
+            db_mock.db.execute.return_value.fetchone.return_value = [1, 2, 3]
+            redis_mock = mock.Mock()
+            redis_mock.get.return_value = self.test_dataset
+            data_set = DatasetType(redis_mock)
+            data_set.set_dataset_key("pheno", "Test")
+            self.assertEqual(data_set("Test"), "Publish")
+            redis_mock.set.assert_called_once_with(
+                "dataset_structure",
+                ('{"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", '
+                 '"Test": "Publish"}'))
+            db_mock.db.execute.assert_called_with(
+                ("SELECT InfoFiles.GN_AccesionId "
+                 "FROM InfoFiles, PublishFreeze, InbredSet "
+                 "WHERE InbredSet.Name = 'Test' AND "
+                 "PublishFreeze.InbredSetId = InbredSet.Id AND "
+                 "InfoFiles.InfoPageName = PublishFreeze.Name")
+            )
+
+    @mock.patch('base.data_set.g')
+    def test_set_dataset_other_pheno(self, db_mock):
+        with app.app_context():
+            db_mock.db.execute.return_value.fetchone.return_value = [1, 2, 3]
+            redis_mock = mock.Mock()
+            redis_mock.get.return_value = self.test_dataset
+            data_set = DatasetType(redis_mock)
+            data_set.set_dataset_key("other_pheno", "Test")
+            self.assertEqual(data_set("Test"), "Publish")
+
+            redis_mock.set.assert_called_once_with(
+                "dataset_structure",
+                ('{"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", '
+                 '"Test": "Publish"}'))
+
+            db_mock.db.execute.assert_called_with(
+                ("SELECT PublishFreeze.Name "
+                 + "FROM PublishFreeze, InbredSet "
+                 + "WHERE InbredSet.Name = 'Test' AND "
+                 "PublishFreeze.InbredSetId = InbredSet.Id")
+            )
+
+    @mock.patch('base.data_set.g')
+    def test_set_dataset_geno(self, db_mock):
+        with app.app_context():
+            db_mock.db.execute.return_value.fetchone.return_value = [1, 2, 3]
+            redis_mock = mock.Mock()
+            redis_mock.get.return_value = self.test_dataset
+            data_set = DatasetType(redis_mock)
+            data_set.set_dataset_key("geno", "Test")
+            self.assertEqual(data_set("Test"), "Geno")
+            redis_mock.set.assert_called_once_with(
+                "dataset_structure",
+                ('{"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", '
+                 '"Test": "Geno"}'))
+
+            db_mock.db.execute.assert_called_with(
+                ("SELECT GenoFreeze.Id FROM "
+                 "GenoFreeze WHERE GenoFreeze.Name = \"Test\" "))
diff --git a/wqflask/tests/unit/base/test_general_object.py b/wqflask/tests/unit/base/test_general_object.py
new file mode 100644
index 00000000..00fd3c72
--- /dev/null
+++ b/wqflask/tests/unit/base/test_general_object.py
@@ -0,0 +1,40 @@
+import unittest
+
+from 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/wqflask/tests/unit/base/test_species.py b/wqflask/tests/unit/base/test_species.py
new file mode 100644
index 00000000..9b5c023c
--- /dev/null
+++ b/wqflask/tests/unit/base/test_species.py
@@ -0,0 +1,116 @@
+"""Tests wqflask/base/species.py"""
+
+import unittest
+from unittest import mock
+from base.species import TheSpecies
+from base.species import IndChromosome
+from base.species import Chromosomes
+from collections import OrderedDict
+from wqflask import app
+from dataclasses import dataclass
+
+
+@dataclass
+class MockChromosome:
+    OrderId: int
+    Name: str
+    Length: int
+
+
+@dataclass
+class MockGroup:
+    name: str
+
+
+@dataclass
+class MockDataset:
+    group: MockGroup
+
+
+class TestTheSpecies(unittest.TestCase):
+    """Tests for TheSpecies class"""
+    @mock.patch('base.species.Chromosomes')
+    def test_create_species_with_null_species_name(self, mock_chromosome):
+        """Test that TheSpecies is instantiated correctly when the
+species_name is provided."""
+        mock_chromosome.return_value = 1
+        test_species = TheSpecies(dataset="random_dataset", species_name="a")
+        self.assertEqual(test_species.name, "a")
+        self.assertEqual(test_species.chromosomes, 1)
+
+    @mock.patch('base.species.Chromosomes')
+    def test_create_species_with_species_name(self, mock_chromosome):
+        """Test that TheSpecies is instantiated correctly when the
+species_name is not provided."""
+        mock_chromosome.return_value = 1
+        test_species = TheSpecies(dataset="random_dataset")
+        self.assertEqual(test_species.dataset, "random_dataset")
+        self.assertEqual(test_species.chromosomes, 1)
+        mock_chromosome.assert_called_once_with(dataset="random_dataset")
+
+
+class TestIndChromosome(unittest.TestCase):
+    """Tests for IndChromosome class"""
+
+    def test_create_ind_chromosome(self):
+        """Test that IndChromosome is instantiated correctly"""
+        test_ind_chromosome = IndChromosome(name="Test", length=10000000)
+        self.assertEqual(test_ind_chromosome.name, "Test")
+        self.assertEqual(test_ind_chromosome.length, 10000000)
+        self.assertEqual(test_ind_chromosome.mb_length, 10)
+
+
+class TestChromosomes(unittest.TestCase):
+    """Tests for Chromosomes class"""
+    maxDiff = None
+
+    def setUp(self):
+        self.app_context = app.app_context()
+        self.app_context.push()
+
+    def tearDown(self):
+        self.app_context.pop()
+
+    @mock.patch("base.species.g")
+    def test_create_chromosomes_with_no_species(self, mock_db):
+        """Test instantiating a chromosome without a species"""
+        mock_db.db.execute.return_value.fetchall.return_value = [
+            MockChromosome(1, "X", 100),
+            MockChromosome(2, "Y", 1000),
+            MockChromosome(3, "Z", 10000),
+        ]
+        mock_dataset = MockDataset(MockGroup("Random"))
+        test_chromosomes = Chromosomes(dataset=mock_dataset)
+        self.assertEqual(
+            list(test_chromosomes.chromosomes.keys()),
+            [1, 2, 3]
+        )
+        self.assertEqual(test_chromosomes.dataset, mock_dataset)
+        mock_db.db.execute.assert_called_with(
+            "SELECT Chr_Length.Name, Chr_Length.OrderId, Length "
+            "FROM Chr_Length, InbredSet WHERE "
+            "Chr_Length.SpeciesId = InbredSet.SpeciesId AND "
+            "InbredSet.Name = 'Random' ORDER BY OrderId"
+        )
+
+    @mock.patch("base.species.g")
+    def test_create_chromosomes_with_species(self, mock_db):
+        """Test instantiating a chromosome with a species"""
+        mock_db.db.execute.return_value.fetchall.return_value = [
+            MockChromosome(1, "X", 100),
+            MockChromosome(2, "Y", 1000),
+            MockChromosome(3, "Z", 10000),
+        ]
+        mock_dataset = MockDataset(MockGroup("Random"))
+        test_chromosomes = Chromosomes(dataset=mock_dataset,
+                                       species="testSpecies")
+        self.assertEqual(
+            list(test_chromosomes.chromosomes.keys()),
+            [1, 2, 3]
+        )
+        mock_db.db.execute.assert_called_with(
+            "SELECT Chr_Length.Name, Chr_Length.OrderId, Length "
+            "FROM Chr_Length, Species WHERE "
+            "Chr_Length.SpeciesId = Species.SpeciesId AND "
+            "Species.Name = 'Testspecies' ORDER BY OrderId"
+        )
diff --git a/wqflask/tests/unit/base/test_trait.py b/wqflask/tests/unit/base/test_trait.py
new file mode 100644
index 00000000..826ccefd
--- /dev/null
+++ b/wqflask/tests/unit/base/test_trait.py
@@ -0,0 +1,241 @@
+# -*- coding: utf-8 -*-
+"""Tests wqflask/base/trait.py"""
+import unittest
+from unittest import mock
+
+from wqflask import app
+from base.trait import GeneralTrait
+from 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'"""
+
+    def setUp(self):
+        self.app_context = app.app_context()
+        self.app_context.push()
+
+    def tearDown(self):
+        self.app_context.pop()
+
+    def test_retrieve_trait_info_with_empty_dataset(self):
+        """Test that an exception is raised when dataset is empty"""
+        with self.assertRaises(AssertionError):
+            retrieve_trait_info(trait=mock.MagicMock(),
+                                dataset={})
+
+    @mock.patch('base.trait.requests.get')
+    @mock.patch('base.trait.g', mock.Mock())
+    def test_retrieve_trait_info_with_empty_trait_info(self,
+                                                       requests_mock):
+        """Empty trait info"""
+        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())
+    def test_retrieve_trait_info_with_non_empty_trait_info(self,
+                                                           requests_mock):
+        """Test that attributes are set"""
+        mock_dataset = mock.MagicMock()
+        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())
+    def test_retrieve_trait_info_utf8_parsing(self,
+                                              requests_mock):
+        """Test that utf-8 strings are parsed correctly"""
+        utf_8_string = "test_string"
+        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 かいと")
+
+    @mock.patch('base.trait.requests.get')
+    @mock.patch('base.trait.g')
+    @mock.patch('base.trait.get_resource_id')
+    def test_retrieve_trait_info_with_non_empty_lrs(self,
+                                                    resource_id_mock,
+                                                    g_mock,
+                                                    requests_mock):
+        """Test retrieve trait info when lrs has a value"""
+        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.37, 3, 4, 5],  # trait_qtl = g.db.execute(query).fetchone()
+            [2.7333, 2.1204]  # 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,
+                         "2.4")
+
+    @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")
+
+    @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/wqflask/tests/unit/base/test_webqtl_case_data.py b/wqflask/tests/unit/base/test_webqtl_case_data.py
new file mode 100644
index 00000000..e1555cb4
--- /dev/null
+++ b/wqflask/tests/unit/base/test_webqtl_case_data.py
@@ -0,0 +1,40 @@
+"""Tests for wqflask/base/webqtlCaseData.py"""
+import unittest
+
+from wqflask import app  # Required because of utility.tools in webqtlCaseData.py
+from 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")
diff --git a/wqflask/tests/unit/utility/__init__.py b/wqflask/tests/unit/utility/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/wqflask/tests/unit/utility/__init__.py
diff --git a/wqflask/tests/unit/utility/test_authentication_tools.py b/wqflask/tests/unit/utility/test_authentication_tools.py
new file mode 100644
index 00000000..024ab43f
--- /dev/null
+++ b/wqflask/tests/unit/utility/test_authentication_tools.py
@@ -0,0 +1,190 @@
+"""Tests for authentication tools"""
+import unittest
+from unittest import mock
+
+from utility.authentication_tools import check_resource_availability
+from utility.authentication_tools import add_new_resource
+
+
+class TestResponse:
+    """Mock Test Response after a request"""
+    @property
+    def content(self):
+        """Mock the content from Requests.get(params).content"""
+        return '["foo"]'
+
+
+class TestUser:
+    """Mock user"""
+    @property
+    def user_id(self):
+        """Mockes user id. Used in Flask.g.user_session.user_id"""
+        return b"Jane"
+
+
+class TestUserSession:
+    """Mock user session"""
+    @property
+    def user_session(self):
+        """Mock user session. Mocks Flask.g.user_session object"""
+        return TestUser()
+
+
+def mock_add_resource(resource_ob, update=False):
+    return resource_ob
+
+
+class TestCheckResourceAvailability(unittest.TestCase):
+    """Test methods related to checking the resource availability"""
+    @mock.patch('utility.authentication_tools.add_new_resource')
+    @mock.patch('utility.authentication_tools.Redis')
+    @mock.patch('utility.authentication_tools.g', TestUserSession())
+    @mock.patch('utility.authentication_tools.get_resource_id')
+    def test_check_resource_availability_default_mask(
+            self,
+            resource_id_mock,
+            redis_mock,
+            add_new_resource_mock):
+        """Test the resource availability with default mask"""
+
+        resource_id_mock.return_value = 1
+        redis_mock.smembers.return_value = []
+        test_dataset = mock.MagicMock()
+        type(test_dataset).type = mock.PropertyMock(return_value="Test")
+        add_new_resource_mock.return_value = {"default_mask": 2}
+        self.assertEqual(check_resource_availability(test_dataset), 2)
+
+    @mock.patch('utility.authentication_tools.requests.get')
+    @mock.patch('utility.authentication_tools.add_new_resource')
+    @mock.patch('utility.authentication_tools.Redis')
+    @mock.patch('utility.authentication_tools.g', TestUserSession())
+    @mock.patch('utility.authentication_tools.get_resource_id')
+    def test_check_resource_availability_non_default_mask(
+            self,
+            resource_id_mock,
+            redis_mock,
+            add_new_resource_mock,
+            requests_mock):
+        """Test the resource availability with non-default mask"""
+        resource_id_mock.return_value = 1
+        redis_mock.smembers.return_value = []
+        add_new_resource_mock.return_value = {"default_mask": 2}
+        requests_mock.return_value = TestResponse()
+        test_dataset = mock.MagicMock()
+        type(test_dataset).type = mock.PropertyMock(return_value="Test")
+        self.assertEqual(check_resource_availability(test_dataset),
+                         ['foo'])
+
+    @mock.patch('utility.authentication_tools.webqtlConfig.SUPER_PRIVILEGES',
+                "SUPERUSER")
+    @mock.patch('utility.authentication_tools.requests.get')
+    @mock.patch('utility.authentication_tools.add_new_resource')
+    @mock.patch('utility.authentication_tools.Redis')
+    @mock.patch('utility.authentication_tools.g', TestUserSession())
+    @mock.patch('utility.authentication_tools.get_resource_id')
+    def test_check_resource_availability_of_super_user(
+            self,
+            resource_id_mock,
+            redis_mock,
+            add_new_resource_mock,
+            requests_mock):
+        """Test the resource availability if the user is the super user"""
+        resource_id_mock.return_value = 1
+        redis_mock.smembers.return_value = [b"Jane"]
+        add_new_resource_mock.return_value = {"default_mask": 2}
+        requests_mock.return_value = TestResponse()
+        test_dataset = mock.MagicMock()
+        type(test_dataset).type = mock.PropertyMock(return_value="Test")
+        self.assertEqual(check_resource_availability(test_dataset),
+                         "SUPERUSER")
+
+    @mock.patch('utility.authentication_tools.webqtlConfig.DEFAULT_PRIVILEGES',
+                "John Doe")
+    def test_check_resource_availability_string_dataset(self):
+        """Test the resource availability if the dataset is a string"""
+        self.assertEqual(check_resource_availability("Test"),
+                         "John Doe")
+
+    @mock.patch('utility.authentication_tools.webqtlConfig.DEFAULT_PRIVILEGES',
+                "John Doe")
+    def test_check_resource_availability_temp(self):
+        """Test the resource availability if the dataset is a string"""
+        test_dataset = mock.MagicMock()
+        type(test_dataset).type = mock.PropertyMock(return_value="Temp")
+        self.assertEqual(check_resource_availability(test_dataset),
+                         "John Doe")
+
+
+class TestAddNewResource(unittest.TestCase):
+    """Test cases for add_new_resource method"""
+    @mock.patch('utility.authentication_tools.webqtlConfig.DEFAULT_PRIVILEGES',
+                "John Doe")
+    @mock.patch('utility.authentication_tools.add_resource', mock_add_resource)
+    @mock.patch('utility.authentication_tools.get_group_code')
+    def test_add_new_resource_if_publish_datatype(self, group_code_mock):
+        """Test add_new_resource if dataset type is 'publish'"""
+        group_code_mock.return_value = "Test"
+        test_dataset = mock.MagicMock()
+        type(test_dataset).type = mock.PropertyMock(return_value="Publish")
+        type(test_dataset).id = mock.PropertyMock(return_value=10)
+        expected_value = {
+            "owner_id": "none",
+            "default_mask": "John Doe",
+            "group_masks": {},
+            "name": "Test_None",
+            "data": {
+                "dataset": 10,
+                "trait": None
+            },
+            "type": "dataset-publish"
+        }
+        self.assertEqual(add_new_resource(test_dataset),
+                         expected_value)
+
+    @mock.patch('utility.authentication_tools.webqtlConfig.DEFAULT_PRIVILEGES',
+                "John Doe")
+    @mock.patch('utility.authentication_tools.add_resource', mock_add_resource)
+    @mock.patch('utility.authentication_tools.get_group_code')
+    def test_add_new_resource_if_geno_datatype(self, group_code_mock):
+        """Test add_new_resource if dataset type is 'geno'"""
+        group_code_mock.return_value = "Test"
+        test_dataset = mock.MagicMock()
+        type(test_dataset).name = mock.PropertyMock(return_value="Geno")
+        type(test_dataset).type = mock.PropertyMock(return_value="Geno")
+        type(test_dataset).id = mock.PropertyMock(return_value=20)
+        expected_value = {
+            "owner_id": "none",
+            "default_mask": "John Doe",
+            "group_masks": {},
+            "name": "Geno",
+            "data": {
+                "dataset": 20,
+            },
+            "type": "dataset-geno"
+        }
+        self.assertEqual(add_new_resource(test_dataset),
+                         expected_value)
+
+    @mock.patch('utility.authentication_tools.webqtlConfig.DEFAULT_PRIVILEGES',
+                "John Doe")
+    @mock.patch('utility.authentication_tools.add_resource', mock_add_resource)
+    @mock.patch('utility.authentication_tools.get_group_code')
+    def test_add_new_resource_if_other_datatype(self, group_code_mock):
+        """Test add_new_resource if dataset type is not 'geno' or 'publish'"""
+        group_code_mock.return_value = "Test"
+        test_dataset = mock.MagicMock()
+        type(test_dataset).name = mock.PropertyMock(return_value="Geno")
+        type(test_dataset).type = mock.PropertyMock(return_value="other")
+        type(test_dataset).id = mock.PropertyMock(return_value=20)
+        expected_value = {
+            "owner_id": "none",
+            "default_mask": "John Doe",
+            "group_masks": {},
+            "name": "Geno",
+            "data": {
+                "dataset": 20,
+            },
+            "type": "dataset-probeset"
+        }
+        self.assertEqual(add_new_resource(test_dataset),
+                         expected_value)
diff --git a/wqflask/tests/unit/utility/test_chunks.py b/wqflask/tests/unit/utility/test_chunks.py
new file mode 100644
index 00000000..1d349193
--- /dev/null
+++ b/wqflask/tests/unit/utility/test_chunks.py
@@ -0,0 +1,20 @@
+"""Test chunking"""
+
+import unittest
+
+from utility.chunks import divide_into_chunks
+
+
+class TestChunks(unittest.TestCase):
+    "Test Utility method for chunking"
+
+    def test_divide_into_chunks(self):
+        "Check that a list is chunked correctly"
+        self.assertEqual(divide_into_chunks([1, 2, 7, 3, 22, 8, 5, 22, 333], 3),
+                         [[1, 2, 7], [3, 22, 8], [5, 22, 333]])
+        self.assertEqual(divide_into_chunks([1, 2, 7, 3, 22, 8, 5, 22, 333], 4),
+                         [[1, 2, 7], [3, 22, 8], [5, 22, 333]])
+        self.assertEqual(divide_into_chunks([1, 2, 7, 3, 22, 8, 5, 22, 333], 5),
+                         [[1, 2], [7, 3], [22, 8], [5, 22], [333]])
+        self.assertEqual(divide_into_chunks([], 5),
+                         [[]])
diff --git a/wqflask/tests/unit/utility/test_corestats.py b/wqflask/tests/unit/utility/test_corestats.py
new file mode 100644
index 00000000..cf91a248
--- /dev/null
+++ b/wqflask/tests/unit/utility/test_corestats.py
@@ -0,0 +1,55 @@
+"""Test Core Stats"""
+
+import unittest
+
+from utility.corestats import Stats
+
+
+class TestChunks(unittest.TestCase):
+    "Test Utility method for chunking"
+
+    def setUp(self):
+        self.stat_test = Stats((x for x in range(1, 11)))
+
+    def test_stats_sum(self):
+        """ Test sequence sum """
+        self.assertEqual(self.stat_test.sum(), 55)
+        self.stat_test = Stats([])
+        self.assertEqual(self.stat_test.sum(), None)
+
+    def test_stats_count(self):
+        """ Test sequence count """
+        self.assertEqual(self.stat_test.count(), 10)
+        self.stat_test = Stats([])
+        self.assertEqual(self.stat_test.count(), 0)
+
+    def test_stats_min(self):
+        """ Test min value in sequence"""
+        self.assertEqual(self.stat_test.min(), 1)
+        self.stat_test = Stats([])
+        self.assertEqual(self.stat_test.min(), None)
+
+    def test_stats_max(self):
+        """ Test max value in sequence """
+        self.assertEqual(self.stat_test.max(), 10)
+        self.stat_test = Stats([])
+        self.assertEqual(self.stat_test.max(), None)
+
+    def test_stats_avg(self):
+        """ Test avg of sequence """
+        self.assertEqual(self.stat_test.avg(), 5.5)
+        self.stat_test = Stats([])
+        self.assertEqual(self.stat_test.avg(), None)
+
+    def test_stats_stdev(self):
+        """ Test standard deviation of sequence """
+        self.assertEqual(self.stat_test.stdev(), 3.0276503540974917)
+        self.stat_test = Stats([])
+        self.assertEqual(self.stat_test.stdev(), None)
+
+    def test_stats_percentile(self):
+        """ Test percentile of sequence """
+        self.assertEqual(self.stat_test.percentile(20), 3.0)
+        self.assertEqual(self.stat_test.percentile(101), None)
+        self.stat_test = Stats([])
+        self.assertEqual(self.stat_test.percentile(20), None)
diff --git a/wqflask/tests/unit/utility/test_corr_result_helpers.py b/wqflask/tests/unit/utility/test_corr_result_helpers.py
new file mode 100644
index 00000000..e196fbdf
--- /dev/null
+++ b/wqflask/tests/unit/utility/test_corr_result_helpers.py
@@ -0,0 +1,32 @@
+""" Test correlation helper methods """
+
+import unittest
+from utility.corr_result_helpers import normalize_values, common_keys, normalize_values_with_samples
+
+
+class TestCorrelationHelpers(unittest.TestCase):
+    """Test methods for normalising lists"""
+
+    def test_normalize_values(self):
+        """Test that a list is normalised correctly"""
+        self.assertEqual(
+            normalize_values([2.3, None, None, 3.2, 4.1, 5], [
+                             3.4, 7.2, 1.3, None, 6.2, 4.1]),
+            ([2.3, 4.1, 5], [3.4, 6.2, 4.1], 3)
+        )
+
+    def test_common_keys(self):
+        """Test that common keys are returned as a list"""
+        a = dict(BXD1=9.113, BXD2=9.825, BXD14=8.985, BXD15=9.300)
+        b = dict(BXD1=9.723, BXD3=9.825, BXD14=9.124, BXD16=9.300)
+        self.assertEqual(sorted(common_keys(a, b)), ['BXD1', 'BXD14'])
+
+    def test_normalize_values_with_samples(self):
+        """Test that a sample(dict) is normalised correctly"""
+        self.assertEqual(
+            normalize_values_with_samples(
+                dict(BXD1=9.113, BXD2=9.825, BXD14=8.985,
+                     BXD15=9.300, BXD20=9.300),
+                dict(BXD1=9.723, BXD3=9.825, BXD14=9.124, BXD16=9.300)),
+            (({'BXD1': 9.113, 'BXD14': 8.985}, {'BXD1': 9.723, 'BXD14': 9.124}, 2))
+        )
diff --git a/wqflask/tests/unit/utility/test_formatting.py b/wqflask/tests/unit/utility/test_formatting.py
new file mode 100644
index 00000000..9d3033d1
--- /dev/null
+++ b/wqflask/tests/unit/utility/test_formatting.py
@@ -0,0 +1,33 @@
+import unittest
+from utility.formatting import numify, commify
+
+
+class TestFormatting(unittest.TestCase):
+    """Test formatting numbers by numifying or commifying"""
+
+    def test_numify(self):
+        "Test that a number is correctly converted to a English readable string"
+        self.assertEqual(numify(1, 'item', 'items'),
+                         'one item')
+        self.assertEqual(numify(2, 'book'), 'two')
+        self.assertEqual(numify(2, 'book', 'books'), 'two books')
+        self.assertEqual(numify(0, 'book', 'books'), 'zero books')
+        self.assertEqual(numify(0), 'zero')
+        self.assertEqual(numify(5), 'five')
+        self.assertEqual(numify(14, 'book', 'books'), '14 books')
+        self.assertEqual(numify(999, 'book', 'books'), '999 books')
+        self.assertEqual(numify(1000000, 'book', 'books'), '1,000,000 books')
+        self.assertEqual(numify(1956), '1956')
+
+    def test_commify(self):
+        "Test that commas are added correctly"
+        self.assertEqual(commify(1), '1')
+        self.assertEqual(commify(123), '123')
+        self.assertEqual(commify(1234), '1234')
+        self.assertEqual(commify(12345), '12,345')
+        self.assertEqual(commify(1234567890), '1,234,567,890')
+        self.assertEqual(commify(123.0), '123.0')
+        self.assertEqual(commify(1234.5), '1234.5')
+        self.assertEqual(commify(1234.56789), '1234.56789')
+        self.assertEqual(commify(123456.789), '123,456.789')
+        self.assertEqual(commify(None), None)
diff --git a/wqflask/tests/unit/utility/test_hmac.py b/wqflask/tests/unit/utility/test_hmac.py
new file mode 100644
index 00000000..13d6261d
--- /dev/null
+++ b/wqflask/tests/unit/utility/test_hmac.py
@@ -0,0 +1,51 @@
+"""Test hmac utility functions"""
+
+import unittest
+from unittest import mock
+
+from utility.hmac import data_hmac
+from utility.hmac import url_for_hmac
+from utility.hmac import hmac_creation
+
+
+class TestHmacUtil(unittest.TestCase):
+    """Test Utility method for hmac creation"""
+
+    @mock.patch("utility.hmac.app.config", {'SECRET_HMAC_CODE': "secret"})
+    def test_hmac_creation(self):
+        """Test hmac creation with a utf-8 string"""
+        self.assertEqual(hmac_creation("ファイ"), "7410466338cfe109e946")
+
+    @mock.patch("utility.hmac.app.config",
+                {'SECRET_HMAC_CODE': ('\x08\xdf\xfa\x93N\x80'
+                                      '\xd9\\H@\\\x9f`\x98d^'
+                                      '\xb4a;\xc6OM\x946a\xbc'
+                                      '\xfc\x80:*\xebc')})
+    def test_hmac_creation_with_cookie(self):
+        """Test hmac creation with a cookie"""
+        cookie = "3f4c1dbf-5b56-4260-87d6-f35445bda37e:af4fcf5eace9e7c864ce"
+        uuid_, _, signature = cookie.partition(":")
+        self.assertEqual(
+            hmac_creation(uuid_),
+            "af4fcf5eace9e7c864ce")
+
+    @mock.patch("utility.hmac.app.config", {'SECRET_HMAC_CODE': "secret"})
+    def test_data_hmac(self):
+        """Test data_hmac fn with a utf-8 string"""
+        self.assertEqual(data_hmac("ファイ"), "ファイ:7410466338cfe109e946")
+
+    @mock.patch("utility.hmac.app.config", {'SECRET_HMAC_CODE': "secret"})
+    @mock.patch("utility.hmac.url_for")
+    def test_url_for_hmac_with_plain_url(self, mock_url):
+        """Test url_for_hmac without params"""
+        mock_url.return_value = "https://mock_url.com/ファイ/"
+        self.assertEqual(url_for_hmac("ファイ"),
+                         "https://mock_url.com/ファイ/?hm=05bc39e659b1948f41e7")
+
+    @mock.patch("utility.hmac.app.config", {'SECRET_HMAC_CODE': "secret"})
+    @mock.patch("utility.hmac.url_for")
+    def test_url_for_hmac_with_param_in_url(self, mock_url):
+        """Test url_for_hmac with params"""
+        mock_url.return_value = "https://mock_url.com/?ファイ=1"
+        self.assertEqual(url_for_hmac("ファイ"),
+                         "https://mock_url.com/?ファイ=1&hm=4709c1708270644aed79")
diff --git a/wqflask/tests/unit/utility/test_type_checking.py b/wqflask/tests/unit/utility/test_type_checking.py
new file mode 100644
index 00000000..48d110c7
--- /dev/null
+++ b/wqflask/tests/unit/utility/test_type_checking.py
@@ -0,0 +1,54 @@
+import unittest
+from utility.type_checking import is_float
+from utility.type_checking import is_int
+from utility.type_checking import is_str
+from utility.type_checking import get_float
+from utility.type_checking import get_int
+from utility.type_checking import get_string
+
+
+class TestTypeChecking(unittest.TestCase):
+    def test_is_float(self):
+        floats = [2, 1.2, '3.1']
+        not_floats = ["String", None, [], ()]
+        for flt in floats:
+            results = is_float(flt)
+            self.assertTrue(results)
+        for nflt in not_floats:
+            results = is_float(nflt)
+            self.assertFalse(results)
+
+    def test_is_int(self):
+        int_values = [1, 1.1]
+        not_int_values = ["string", None, [], "1.1"]
+        for int_val in int_values:
+            results = is_int(int_val)
+            self.assertTrue(results)
+        for not_int in not_int_values:
+            results = is_int(not_int)
+            self.assertFalse(results)
+
+    def test_is_str(self):
+        string_values = [1, False, [], {}, "string_value"]
+        falsey_values = [None]
+        for string_val in string_values:
+            results = is_str(string_val)
+            self.assertTrue(results)
+        for non_string in falsey_values:
+            results = is_str(non_string)
+            self.assertFalse(results)
+
+    def test_get_float(self):
+        vars_object = {"min_value": "12"}
+        results = get_float(vars_object, "min_value")
+        self.assertEqual(results, 12.0)
+
+    def test_get_int(self):
+        vars_object = {"lx_value": "1"}
+        results = get_int(vars_object, "lx_value")
+        self.assertEqual(results, 1)
+
+    def test_get_string(self):
+        string_object = {"mx_value": 1}
+        results = get_string(string_object, "mx_value")
+        self.assertEqual(results, "1")
\ No newline at end of file
diff --git a/wqflask/tests/unit/wqflask/__init__.py b/wqflask/tests/unit/wqflask/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/wqflask/tests/unit/wqflask/__init__.py
diff --git a/wqflask/tests/unit/wqflask/api/__init__.py b/wqflask/tests/unit/wqflask/api/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/wqflask/tests/unit/wqflask/api/__init__.py
diff --git a/wqflask/tests/unit/wqflask/api/test_correlation.py b/wqflask/tests/unit/wqflask/api/test_correlation.py
new file mode 100644
index 00000000..1089a36f
--- /dev/null
+++ b/wqflask/tests/unit/wqflask/api/test_correlation.py
@@ -0,0 +1,153 @@
+import unittest
+from unittest import mock
+from wqflask import app
+from collections import OrderedDict
+from wqflask.api.correlation import init_corr_params
+from wqflask.api.correlation import convert_to_mouse_gene_id
+from wqflask.api.correlation import do_literature_correlation_for_all_traits
+from wqflask.api.correlation import get_sample_r_and_p_values
+from wqflask.api.correlation import calculate_results
+
+
+class AttributeSetter:
+    def __init__(self, obj):
+        for k, v in obj.items():
+            setattr(self, k, v)
+
+
+class MockDataset(AttributeSetter):
+    def get_trait_data(self):
+        return None
+
+    def retrieve_genes(self, id=None):
+        return {
+            "TT-1": "GH-1",
+            "TT-2": "GH-2",
+            "TT-3": "GH-3"
+
+        }
+
+
+class TestCorrelations(unittest.TestCase):
+    def setUp(self):
+        self.app_context = app.app_context()
+        self.app_context.push()
+
+    def tearDown(self):
+        self.app_context.pop()
+
+    def test_init_corr_params(self):
+        start_vars = {
+            "return_count": "3",
+            "type": "T1",
+            "method": "spearman"
+        }
+
+        corr_params_results = init_corr_params(start_vars=start_vars)
+        expected_results = {
+            "return_count": 3,
+            "type": "T1",
+            "method": "spearman"
+        }
+
+        self.assertEqual(corr_params_results, expected_results)
+
+    @mock.patch("wqflask.api.correlation.g")
+    def test_convert_to_mouse_gene_id(self, mock_db):
+
+        results = convert_to_mouse_gene_id(species="Other", gene_id="")
+        self.assertEqual(results, None)
+
+        rat_species_results = convert_to_mouse_gene_id(
+            species="rat", gene_id="GH1")
+
+        mock_db.db.execute.return_value.fetchone.side_effect = [
+            AttributeSetter({"mouse": "MG-1"}), AttributeSetter({"mouse": "MG-2"})]
+
+        self.assertEqual(convert_to_mouse_gene_id(
+            species="mouse", gene_id="MG-4"), "MG-4")
+        self.assertEqual(convert_to_mouse_gene_id(
+            species="rat", gene_id="R1"), "MG-1")
+        self.assertEqual(convert_to_mouse_gene_id(
+            species="human", gene_id="H1"), "MG-2")
+
+    @mock.patch("wqflask.api.correlation.g")
+    @mock.patch("wqflask.api.correlation.convert_to_mouse_gene_id")
+    def test_do_literature_correlation_for_all_traits(self, mock_convert_to_mouse_geneid, mock_db):
+        mock_convert_to_mouse_geneid.side_effect = [
+            "MG-1", "MG-2;", "MG-3", "MG-4"]
+
+        trait_geneid_dict = {
+            "TT-1": "GH-1",
+            "TT-2": "GH-2",
+            "TT-3": "GH-3"
+
+        }
+        mock_db.db.execute.return_value.fetchone.side_effect = [AttributeSetter(
+            {"value": "V1"}), AttributeSetter({"value": "V2"}), AttributeSetter({"value": "V3"})]
+
+        this_trait = AttributeSetter({"geneid": "GH-1"})
+
+        target_dataset = AttributeSetter(
+            {"group": AttributeSetter({"species": "rat"})})
+        results = do_literature_correlation_for_all_traits(
+            this_trait=this_trait, target_dataset=target_dataset, trait_geneid_dict=trait_geneid_dict, corr_params={})
+
+        expected_results = {'TT-1': ['GH-1', 0],
+                            'TT-2': ['GH-2', 'V1'], 'TT-3': ['GH-3', 'V2']}
+        self.assertEqual(results, expected_results)
+
+    @mock.patch("wqflask.api.correlation.corr_result_helpers.normalize_values")
+    def test_get_sample_r_and_p_values(self, mock_normalize):
+
+        group = AttributeSetter(
+            {"samplelist": ["S1", "S2", "S3", "S4", "S5", "S6", "S7"]})
+        target_dataset = AttributeSetter({"group": group})
+
+        target_vals = [3.4, 6.2, 4.1, 3.4, 1.2, 5.6]
+        trait_data = {"S1": AttributeSetter({"value": 2.3}), "S2": AttributeSetter({"value": 1.1}),
+                      "S3": AttributeSetter(
+            {"value": 6.3}), "S4": AttributeSetter({"value": 3.6}), "S5": AttributeSetter({"value": 4.1}),
+            "S6": AttributeSetter({"value": 5.0})}
+        this_trait = AttributeSetter({"data": trait_data})
+        mock_normalize.return_value = ([2.3, 1.1, 6.3, 3.6, 4.1, 5.0],
+                                       [3.4, 6.2, 4.1, 3.4, 1.2, 5.6], 6)
+        mock_normalize.side_effect = [([2.3, 1.1, 6.3, 3.6, 4.1, 5.0],
+                                       [3.4, 6.2, 4.1, 3.4, 1.2, 5.6], 6),
+                                      ([2.3, 1.1, 6.3, 3.6, 4.1, 5.0],
+                                       [3.4, 6.2, 4.1, 3.4, 1.2, 5.6], 6),
+                                      ([2.3, 1.1, 1.4], [3.4, 6.2, 4.1], 3)]
+
+        results_pearsonr = get_sample_r_and_p_values(this_trait=this_trait, this_dataset={
+        }, target_vals=target_vals, target_dataset=target_dataset, type="pearson")
+        results_spearmanr = get_sample_r_and_p_values(this_trait=this_trait, this_dataset={
+        }, target_vals=target_vals, target_dataset=target_dataset, type="spearman")
+        results_num_overlap = get_sample_r_and_p_values(this_trait=this_trait, this_dataset={
+        }, target_vals=target_vals, target_dataset=target_dataset, type="pearson")
+        expected_pearsonr = [-0.21618688834430866, 0.680771605997119, 6]
+        expected_spearmanr = [-0.11595420713048969, 0.826848213385815, 6]
+        for i, val in enumerate(expected_pearsonr):
+            self.assertAlmostEqual(val, results_pearsonr[i], 4)
+        for i, val in enumerate(expected_spearmanr):
+            self.assertAlmostEqual(val, results_spearmanr[i], 4)
+        self.assertEqual(results_num_overlap, None)
+
+    @mock.patch("wqflask.api.correlation.do_literature_correlation_for_all_traits")
+    def test_calculate_results(self, literature_correlation):
+
+        literature_correlation.return_value = {
+            'TT-1': ['GH-1', 0], 'TT-2': ['GH-2', 3], 'TT-3': ['GH-3', 1]}
+
+        this_dataset = MockDataset(
+            {"group": AttributeSetter({"species": "rat"})})
+        target_dataset = MockDataset(
+            {"group": AttributeSetter({"species": "rat"})})
+        this_trait = AttributeSetter({"geneid": "GH-1"})
+        corr_params = {"type": "literature"}
+        sorted_results = calculate_results(
+            this_trait=this_trait, this_dataset=this_dataset, target_dataset=target_dataset, corr_params=corr_params)
+        expected_results = {'TT-2': ['GH-2', 3],
+                            'TT-3': ['GH-3', 1], 'TT-1': ['GH-1', 0]}
+
+        self.assertTrue(isinstance(sorted_results, OrderedDict))
+        self.assertEqual(dict(sorted_results), expected_results)
diff --git a/wqflask/tests/unit/wqflask/api/test_gen_menu.py b/wqflask/tests/unit/wqflask/api/test_gen_menu.py
new file mode 100644
index 00000000..7e477da2
--- /dev/null
+++ b/wqflask/tests/unit/wqflask/api/test_gen_menu.py
@@ -0,0 +1,423 @@
+"""Test cases for wqflask.api.gen_menu"""
+import unittest
+from unittest import mock
+
+from wqflask.api.gen_menu import gen_dropdown_json
+from wqflask.api.gen_menu import get_groups
+from wqflask.api.gen_menu import get_types
+from wqflask.api.gen_menu import get_datasets
+from wqflask.api.gen_menu import phenotypes_exist
+from wqflask.api.gen_menu import genotypes_exist
+from wqflask.api.gen_menu import build_datasets
+from wqflask.api.gen_menu import build_types
+
+
+class TestGenMenu(unittest.TestCase):
+    """Tests for the gen_menu module"""
+
+    def setUp(self):
+        self.test_group = {
+            'mouse': [
+                ['H_T1',
+                 'H_T',
+                 'Family:DescriptionA'
+                 ],
+                ['H_T2', "H_T'", 'Family:None']
+            ],
+            'human': [
+                ['BXD', 'BXD', 'Family:None'],
+                ['HLC', 'Liver: Normal Gene Expression with Genotypes (Merck)',
+                 'Family:Test']
+            ]
+        }
+
+        self.test_type = {
+            'mouse': {
+                'H_T2': [('Phenotypes',
+                          'Traits and Cofactors',
+                          'Phenotypes'),
+                         ('Genotypes',
+                          'DNA Markers and SNPs',
+                          'Genotypes'),
+                         ['M', 'M', 'Molecular Trait Datasets']],
+                'H_T1': [('Phenotypes',
+                          'Traits and Cofactors',
+                          'Phenotypes'),
+                         ('Genotypes',
+                          'DNA Markers and SNPs',
+                          'Genotypes'),
+                         ['M', 'M', 'Molecular Trait Datasets']]
+            },
+            'human': {
+                'HLC': [('Phenotypes',
+                         'Traits and Cofactors',
+                         'Phenotypes'),
+                        ('Genotypes',
+                         'DNA Markers and SNPs',
+                         'Genotypes'),
+                        ['M', 'M', 'Molecular Trait Datasets']],
+                'BXD': [('Phenotypes',
+                         'Traits and Cofactors',
+                         'Phenotypes'),
+                        ('Genotypes',
+                         'DNA Markers and SNPs',
+                         'Genotypes'),
+                        ['M', 'M', 'Molecular Trait Datasets']]
+            }
+        }
+
+    def test_get_groups(self):
+        """Test that species groups are grouped correctly"""
+        db_mock = mock.MagicMock()
+        with db_mock.cursor() as cursor:
+            cursor.fetchall.side_effect = [
+                # Mouse
+                (('BXD', 'BXD', None),
+                 ('HLC', ('Liver: Normal Gene Expression '
+                          'with Genotypes (Merck)'),
+                  'Test')),
+                # Human
+                (('H_T1', "H_T", "DescriptionA"),
+                 ('H_T2', "H_T'", None))
+            ]
+            self.assertEqual(get_groups([["human", "Human"],
+                                         ["mouse", "Mouse"]],
+                                        db_mock),
+                             self.test_group)
+
+            for name in ["mouse", "human"]:
+                cursor.execute.assert_any_call(
+                    ("SELECT InbredSet.Name, InbredSet.FullName, "
+                     "IFNULL(InbredSet.Family, 'None') "
+                     "FROM InbredSet, Species WHERE Species.Name "
+                     "= '{}' AND InbredSet.SpeciesId = Species.Id GROUP by "
+                     "InbredSet.Name ORDER BY IFNULL(InbredSet.FamilyOrder, "
+                     "InbredSet.FullName) ASC, IFNULL(InbredSet.Family, "
+                     "InbredSet.FullName) ASC, InbredSet.FullName ASC, "
+                     "InbredSet.MenuOrderId ASC").format(name)
+                )
+
+    def test_phenotypes_exist_called_with_correct_query(self):
+        """Test that phenotypes_exist is called with the correct query"""
+        db_mock = mock.MagicMock()
+        with db_mock.cursor() as cursor:
+            cursor.fetchone.return_value = None
+            phenotypes_exist("test", db_mock)
+            cursor.execute.assert_called_with(
+                "SELECT Name FROM PublishFreeze "
+                "WHERE PublishFreeze.Name = 'testPublish'"
+            )
+
+    def test_phenotypes_exist_with_falsy_values(self):
+        """Test that phenotype check returns correctly when given
+        a None value"""
+        db_mock = mock.MagicMock()
+        with db_mock.cursor() as cursor:
+            for x in [None, False, (), [], ""]:
+                cursor.fetchone.return_value = x
+            self.assertFalse(phenotypes_exist("test", db_mock))
+
+    def test_phenotypes_exist_with_truthy_value(self):
+        """Test that phenotype check returns correctly when given Truthy"""
+        db_mock = mock.MagicMock()
+        with db_mock.cursor() as conn:
+            with conn.cursor() as cursor:
+                for x in ["x", ("result"), ["result"], [1]]:
+                    cursor.fetchone.return_value = (x)
+                self.assertTrue(phenotypes_exist("test", db_mock))
+
+    def test_genotypes_exist_called_with_correct_query(self):
+        """Test that genotypes_exist is called with the correct query"""
+        db_mock = mock.MagicMock()
+        with db_mock.cursor() as cursor:
+            cursor.fetchone.return_value = None
+            genotypes_exist("test", db_mock)
+            cursor.execute.assert_called_with(
+                "SELECT Name FROM GenoFreeze WHERE "
+                "GenoFreeze.Name = 'testGeno'"
+            )
+
+    def test_genotypes_exist_with_falsy_values(self):
+        """Test that genotype check returns correctly when given a None value
+
+        """
+        db_mock = mock.MagicMock()
+        with db_mock.cursor() as cursor:
+            for x in [None, False, (), [], ""]:
+                cursor.fetchone.return_value = x
+                self.assertFalse(genotypes_exist("test", db_mock))
+
+    def test_genotypes_exist_with_truthy_value(self):
+        """Test that genotype check returns correctly when given Truthy """
+        db_mock = mock.MagicMock()
+        with db_mock.cursor() as cursor:
+            for x in ["x", ("result"), ["result"], [1]]:
+                cursor.fetchone.return_value = (x)
+                self.assertTrue(phenotypes_exist("test", db_mock))
+
+    def test_build_datasets_with_type_phenotypes(self):
+        """Test that correct dataset is returned for a phenotype type"""
+        db_mock = mock.MagicMock()
+        with db_mock.cursor() as cursor:
+            cursor.fetchall.return_value = (
+                (602, "BXDPublish", "BXD Published Phenotypes"),
+            )
+            self.assertEqual(build_datasets("Mouse", "BXD",
+                                            "Phenotypes", db_mock),
+                             [['602', "BXDPublish",
+                               "BXD Published Phenotypes"]])
+            cursor.execute.assert_called_with(
+                "SELECT InfoFiles.GN_AccesionId, PublishFreeze.Name, "
+                + "PublishFreeze.FullName FROM InfoFiles, PublishFreeze, "
+                + "InbredSet WHERE InbredSet.Name = 'BXD' AND "
+                + "PublishFreeze.InbredSetId = InbredSet.Id AND "
+                + "InfoFiles.InfoPageName = PublishFreeze.Name "
+                + "ORDER BY PublishFreeze.CreateTime ASC"
+            )
+            self.assertEqual(build_datasets("Mouse", "MDP",
+                                            "Phenotypes", db_mock),
+                             [['602', "BXDPublish",
+                               "Mouse Phenome Database"]])
+
+            cursor.fetchall.return_value = ()
+            cursor.fetchone.return_value = (
+                "BXDPublish", "Mouse Phenome Database"
+            )
+            self.assertEqual(build_datasets("Mouse", "MDP",
+                                            "Phenotypes", db_mock),
+                             [["None", "BXDPublish",
+                               "Mouse Phenome Database"]])
+
+    def test_build_datasets_with_type_phenotypes_and_no_results(self):
+        """Test that correct dataset is returned for a phenotype type with no
+        results
+
+        """
+        db_mock = mock.MagicMock()
+        with db_mock.cursor() as cursor:
+            cursor.fetchall.return_value = None
+            cursor.fetchone.return_value = (121,
+                                            "text value")
+            self.assertEqual(build_datasets("Mouse", "BXD",
+                                            "Phenotypes", db_mock),
+                             [["None", "121",
+                               "text value"]])
+            cursor.execute.assert_called_with(
+                "SELECT PublishFreeze.Name, PublishFreeze.FullName "
+                "FROM PublishFreeze, InbredSet "
+                "WHERE InbredSet.Name = 'BXD' AND "
+                "PublishFreeze.InbredSetId = InbredSet.Id "
+                "ORDER BY PublishFreeze.CreateTime ASC"
+            )
+
+    def test_build_datasets_with_type_genotypes(self):
+        """Test that correct dataset is returned for a phenotype type"""
+        db_mock = mock.MagicMock()
+        with db_mock.cursor() as cursor:
+            cursor.fetchone.return_value = (
+                635, "HLCPublish", "HLC Published Genotypes"
+            )
+            self.assertEqual(build_datasets("Mouse", "HLC",
+                                            "Genotypes", db_mock),
+                             [["635", "HLCGeno", "HLC Genotypes"]])
+            cursor.execute.assert_called_with(
+                "SELECT InfoFiles.GN_AccesionId FROM InfoFiles, "
+                "GenoFreeze, InbredSet WHERE InbredSet.Name = 'HLC' AND "
+                "GenoFreeze.InbredSetId = InbredSet.Id AND "
+                "InfoFiles.InfoPageName = GenoFreeze.ShortName "
+                "ORDER BY GenoFreeze.CreateTime DESC"
+            )
+            cursor.fetchone.return_value = ()
+            self.assertEqual(build_datasets("Mouse", "HLC",
+                                            "Genotypes", db_mock),
+                             [["None", "HLCGeno", "HLC Genotypes"]])
+
+    def test_build_datasets_with_type_mrna(self):
+        """Test that correct dataset is returned for a mRNA
+        expression/ Probeset"""
+        db_mock = mock.MagicMock()
+        with db_mock.cursor() as cursor:
+            cursor.fetchall.return_value = (
+                (112, "HC_M2_0606_P",
+                 "Hippocampus Consortium M430v2 (Jun06) PDNN"), )
+            self.assertEqual(build_datasets("Mouse",
+                                            "HLC", "mRNA", db_mock),
+                             [["112", 'HC_M2_0606_P',
+                               "Hippocampus Consortium M430v2 (Jun06) PDNN"
+                               ]])
+            cursor.execute.assert_called_once_with(
+                "SELECT ProbeSetFreeze.Id, ProbeSetFreeze.Name, "
+                "ProbeSetFreeze.FullName FROM ProbeSetFreeze, "
+                "ProbeFreeze, InbredSet, Tissue, Species WHERE "
+                "Species.Name = 'Mouse' AND Species.Id = "
+                "InbredSet.SpeciesId AND InbredSet.Name = 'HLC' AND "
+                "ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id AND "
+                "Tissue.Name = 'mRNA' AND ProbeFreeze.TissueId = "
+                "Tissue.Id AND ProbeFreeze.InbredSetId = InbredSet.Id AND "
+                "ProbeSetFreeze.public > 0 "
+                "ORDER BY -ProbeSetFreeze.OrderList DESC, "
+                "ProbeSetFreeze.CreateTime DESC")
+
+    @mock.patch('wqflask.api.gen_menu.build_datasets')
+    def test_build_types(self, datasets_mock):
+        """Test that correct tissue metadata is returned"""
+        db_mock = mock.MagicMock()
+        datasets_mock.return_value = [
+            ["112", 'HC_M2_0606_P',
+                "Hippocampus Consortium M430v2 (Jun06) PDNN"]
+        ]
+        with db_mock.cursor() as cursor:
+            cursor.fetchall.return_value = (
+                ('Mouse Tissue'), ('Human Tissue'), ('Rat Tissue')
+            )
+            self.assertEqual(build_types('mouse', 'random group', db_mock),
+                             [['M', 'M', 'Molecular Traits'],
+                              ['H', 'H', 'Molecular Traits'],
+                              ['R', 'R', 'Molecular Traits']])
+            cursor.execute.assert_called_once_with(
+                "SELECT DISTINCT Tissue.Name "
+                "FROM ProbeFreeze, ProbeSetFreeze, InbredSet, "
+                "Tissue, Species WHERE Species.Name = 'mouse' "
+                "AND Species.Id = InbredSet.SpeciesId AND "
+                "InbredSet.Name = 'random group' AND "
+                "ProbeFreeze.TissueId = Tissue.Id AND "
+                "ProbeFreeze.InbredSetId = InbredSet.Id AND "
+                "ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id "
+                "ORDER BY Tissue.Name"
+            )
+
+    @mock.patch('wqflask.api.gen_menu.build_types')
+    @mock.patch('wqflask.api.gen_menu.genotypes_exist')
+    @mock.patch('wqflask.api.gen_menu.phenotypes_exist')
+    def test_get_types_with_existing_genotype_and_phenotypes(
+            self,
+            phenotypes_exist_mock,
+            genotypes_exist_mock,
+            build_types_mock):
+        """Test that build types are constructed correctly if phenotypes and genotypes
+        exist
+
+        """
+        phenotypes_exist_mock.return_value = True
+        genotypes_exist_mock.return_value = True
+
+        expected_result = self.test_type
+
+        build_types_mock.return_value = [
+            ['M', 'M', 'Molecular Trait Datasets']
+        ]
+        self.assertEqual(get_types(self.test_group,
+                                   mock.MagicMock()),
+                         expected_result)
+
+    @mock.patch('wqflask.api.gen_menu.build_types')
+    @mock.patch('wqflask.api.gen_menu.genotypes_exist')
+    @mock.patch('wqflask.api.gen_menu.phenotypes_exist')
+    def test_get_types_with_buildtype_and_non_existent_genotype_and_phenotypes(
+            self,
+            phenotypes_exist_mock,
+            genotypes_exist_mock,
+            build_types_mock):
+        """Test that build types are constructed correctly if phenotypes_exist and
+        genotypes_exist are false but build_type is falsy
+
+        """
+        phenotypes_exist_mock.return_value = False
+        genotypes_exist_mock.return_value = False
+
+        build_types_mock.return_value = []
+        self.assertEqual(get_types(self.test_group, mock.MagicMock()),
+                         {'mouse': {}, 'human': {}})
+
+    @mock.patch('wqflask.api.gen_menu.build_types')
+    @mock.patch('wqflask.api.gen_menu.genotypes_exist')
+    @mock.patch('wqflask.api.gen_menu.phenotypes_exist')
+    def test_get_types_with_non_existent_genotype_phenotypes_and_buildtype(
+            self,
+            phenotypes_exist_mock,
+            genotypes_exist_mock,
+            build_types_mock):
+        """Test that build types are constructed correctly if phenotypes_exist,
+        genotypes_exist and build_types are truthy
+
+        """
+        phenotypes_exist_mock.return_value = False
+        genotypes_exist_mock.return_value = False
+
+        build_types_mock.return_value = [
+            ['M', 'M', 'Molecular Trait Datasets']
+        ]
+        expected_result = {
+            'mouse': {
+                'H_T2': [['M', 'M', 'Molecular Trait Datasets']],
+                'H_T1': [['M', 'M', 'Molecular Trait Datasets']]},
+            'human': {
+                'HLC': [['M', 'M', 'Molecular Trait Datasets']],
+                'BXD': [['M', 'M', 'Molecular Trait Datasets']]}}
+        self.assertEqual(get_types(self.test_group, mock.MagicMock()),
+                         expected_result)
+
+    @mock.patch('wqflask.api.gen_menu.build_datasets')
+    def test_get_datasets_with_existent_datasets(self,
+                                                 build_datasets_mock):
+        """Test correct dataset is returned with existent build_datasets"""
+        build_datasets_mock.return_value = "Test"
+        expected_result = {
+            'mouse': {
+                'H_T2': {'Genotypes': 'Test',
+                         'M': 'Test',
+                         'Phenotypes': 'Test'},
+                'H_T1': {'Genotypes': 'Test',
+                         'M': 'Test',
+                         'Phenotypes': 'Test'}},
+            'human': {'HLC': {'Genotypes': 'Test',
+                              'M': 'Test',
+                              'Phenotypes': 'Test'},
+                      'BXD': {'Genotypes': 'Test',
+                              'M': 'Test',
+                              'Phenotypes': 'Test'}}}
+        self.assertEqual(get_datasets(self.test_type, mock.MagicMock()),
+                         expected_result)
+
+    @mock.patch('wqflask.api.gen_menu.build_datasets')
+    def test_get_datasets_with_non_existent_datasets(self,
+                                                     build_datasets_mock):
+        """Test correct dataset is returned with non-existent build_datasets"""
+        build_datasets_mock.return_value = None
+        expected_result = {
+            'mouse': {
+                'H_T2': {},
+                'H_T1': {}},
+            'human': {'HLC': {},
+                      'BXD': {}}}
+        self.assertEqual(get_datasets(self.test_type, mock.MagicMock()),
+                         expected_result)
+
+    @mock.patch('wqflask.api.gen_menu.get_datasets')
+    @mock.patch('wqflask.api.gen_menu.get_types')
+    @mock.patch('wqflask.api.gen_menu.get_groups')
+    @mock.patch('wqflask.api.gen_menu.get_all_species')
+    def test_gen_dropdown_json(self,
+                               species_mock,
+                               groups_mock,
+                               types_mock,
+                               datasets_mock):
+        "Test that the correct dictionary is constructed properly"
+        species_mock.return_value = ("speciesA speciesB speciesC speciesD"
+                                     .split(" "))
+        datasets_mock.return_value = ("datasetA datasetB datasetC datasetD"
+                                      .split(" "))
+        groups_mock.return_value = ("groupA groupB groupC groupD"
+                                    .split(" "))
+        types_mock.return_value = ("typeA typeB typeC typeD"
+                                   .split(" "))
+        datasets_mock.return_value = ("datasetA datasetB datasetC datasetD"
+                                      .split(" "))
+
+        expected_result = {
+            'datasets': ['datasetA', 'datasetB', 'datasetC', 'datasetD'],
+            'types': ['typeA', 'typeB', 'typeC', 'typeD'],
+            'groups': ['groupA', 'groupB', 'groupC', 'groupD'],
+            'species': ['speciesA', 'speciesB', 'speciesC', 'speciesD']}
+
+        self.assertEqual(gen_dropdown_json(mock.MagicMock()), expected_result)
diff --git a/wqflask/tests/unit/wqflask/api/test_mapping.py b/wqflask/tests/unit/wqflask/api/test_mapping.py
new file mode 100644
index 00000000..159c982b
--- /dev/null
+++ b/wqflask/tests/unit/wqflask/api/test_mapping.py
@@ -0,0 +1,108 @@
+import unittest
+from unittest import mock
+from wqflask.api.mapping import initialize_parameters
+from wqflask.api.mapping import do_mapping_for_api
+
+
+class AttributeSetter:
+    def __init__(self, obj):
+        for key, value in obj.items():
+            setattr(self, key, value)
+
+
+class MockGroup(AttributeSetter):
+    def get_marker(self):
+        self.markers = []
+
+
+class TestMapping(unittest.TestCase):
+
+    def test_initialize_parameters(self):
+        expected_results = {
+            "format": "json",
+            "limit_to": False,
+            "mapping_method": "gemma",
+            "maf": 0.01,
+            "use_loco": True,
+            "num_perm": 0,
+            "perm_check": False
+        }
+
+        results = initialize_parameters(
+            start_vars={}, dataset={}, this_trait={})
+        self.assertEqual(results, expected_results)
+
+        start_vars = {
+            "format": "F1",
+            "limit_to": "1",
+            "mapping_method": "rqtl",
+            "control_marker": True,
+            "pair_scan": "true",
+            "interval_mapping": "true",
+            "use_loco": "true",
+            "num_perm": "14"
+
+        }
+
+        results_2 = initialize_parameters(
+            start_vars=start_vars, dataset={}, this_trait={})
+        expected_results = {
+            "format": "F1",
+            "limit_to": 1,
+            "mapping_method": "gemma",
+            "maf": 0.01,
+            "use_loco": True,
+            "num_perm": 14,
+            "perm_check": "ON"
+        }
+
+        self.assertEqual(results_2, expected_results)
+
+    @mock.patch("wqflask.api.mapping.rqtl_mapping.run_rqtl")
+    @mock.patch("wqflask.api.mapping.gemma_mapping.run_gemma")
+    @mock.patch("wqflask.api.mapping.initialize_parameters")
+    @mock.patch("wqflask.api.mapping.retrieve_sample_data")
+    @mock.patch("wqflask.api.mapping.create_trait")
+    @mock.patch("wqflask.api.mapping.data_set.create_dataset")
+    def test_do_mapping_for_api(self, mock_create_dataset, mock_trait, mock_retrieve_sample, mock_param, run_gemma, run_rqtl_geno):
+        start_vars = {
+            "db": "Temp",
+            "trait_id": "dewf3232rff2",
+            "format": "F1",
+            "mapping_method": "gemma",
+            "use_loco": True
+
+        }
+        sampleList = ["S1", "S2", "S3", "S4"]
+        samplelist = ["S1", "S2", "S4"]
+        dataset = AttributeSetter({"group": samplelist})
+        this_trait = AttributeSetter({})
+        trait_data = AttributeSetter({
+            "data": {
+                "item1": AttributeSetter({"name": "S1", "value": "S1_value"}),
+                "item2": AttributeSetter({"name": "S2", "value": "S2_value"}),
+                "item3": AttributeSetter({"name": "S3", "value": "S3_value"}),
+
+            }
+        })
+        trait = AttributeSetter({
+            "data": trait_data
+        })
+
+        dataset.return_value = dataset
+        mock_trait.return_value = this_trait
+
+        mock_retrieve_sample.return_value = trait
+        mock_param.return_value = {
+            "format": "F1",
+            "limit_to": False,
+            "mapping_method": "gemma",
+            "maf": 0.01,
+            "use_loco": "True",
+            "num_perm": 14,
+            "perm_check": "ON"
+        }
+
+        run_gemma.return_value = ["results"]
+        results = do_mapping_for_api(start_vars=start_vars)
+        self.assertEqual(results, ("results", None))
diff --git a/wqflask/tests/unit/wqflask/api/test_markdown_routes.py b/wqflask/tests/unit/wqflask/api/test_markdown_routes.py
new file mode 100644
index 00000000..1c513ac5
--- /dev/null
+++ b/wqflask/tests/unit/wqflask/api/test_markdown_routes.py
@@ -0,0 +1,54 @@
+"""Test functions for wqflask/api/markdown.py"""
+
+import unittest
+from unittest import mock
+
+from dataclasses import dataclass
+from wqflask.api.markdown import render_markdown
+
+
+@dataclass
+class MockRequests404:
+    status_code: int = 404
+
+
+@dataclass
+class MockRequests200:
+    status_code: int = 200
+    content: str = b"""
+# Glossary
+This is some content
+
+## Sub-heading
+This is another sub-heading"""
+
+
+class TestMarkdownRoutesFunctions(unittest.TestCase):
+    """Test cases for functions in markdown"""
+
+    @mock.patch('wqflask.api.markdown.requests.get')
+    def test_render_markdown_when_fetching_locally(self, requests_mock):
+        requests_mock.return_value = MockRequests404()
+        markdown_content = render_markdown("general/glossary/glossary.md")
+        requests_mock.assert_called_with(
+            "https://raw.githubusercontent.com"
+            "/genenetwork/gn-docs/"
+            "master/general/"
+            "glossary/glossary.md")
+        self.assertRegexpMatches(markdown_content,
+                                 "Content for general/glossary/glossary.md not available.")
+
+    @mock.patch('wqflask.api.markdown.requests.get')
+    def test_render_markdown_when_fetching_remotely(self, requests_mock):
+        requests_mock.return_value = MockRequests200()
+        markdown_content = render_markdown("general/glossary/glossary.md")
+        requests_mock.assert_called_with(
+            "https://raw.githubusercontent.com"
+            "/genenetwork/gn-docs/"
+            "master/general/"
+            "glossary/glossary.md")
+        self.assertEqual("""<h1>Glossary</h1>
+<p>This is some content</p>
+<h2>Sub-heading</h2>
+<p>This is another sub-heading</p>""",
+                         markdown_content)
diff --git a/wqflask/tests/unit/wqflask/correlation/__init__.py b/wqflask/tests/unit/wqflask/correlation/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/wqflask/tests/unit/wqflask/correlation/__init__.py
diff --git a/wqflask/tests/unit/wqflask/correlation/test_correlation_functions.py b/wqflask/tests/unit/wqflask/correlation/test_correlation_functions.py
new file mode 100644
index 00000000..a8cf6006
--- /dev/null
+++ b/wqflask/tests/unit/wqflask/correlation/test_correlation_functions.py
@@ -0,0 +1,40 @@
+"""module contains tests for correlation functions"""
+
+import unittest
+from unittest import mock
+
+from wqflask.correlation.correlation_functions import get_trait_symbol_and_tissue_values
+from wqflask.correlation.correlation_functions import cal_zero_order_corr_for_tiss
+
+
+class TestCorrelationFunctions(unittest.TestCase):
+    """test for correlation helper functions"""
+
+    @mock.patch("wqflask.correlation.correlation_functions.compute_corr_coeff_p_value")
+    def test_tissue_corr_computation(self, mock_tiss_corr_computation):
+        """test for cal_zero_order_corr_for_tiss"""
+
+        primary_values = [9.288, 9.313, 8.988, 9.660, 8.21]
+        target_values = [9.586, 8.498, 9.362, 8.820, 8.786]
+
+        mock_tiss_corr_computation.return_value = (0.51, 0.7)
+
+        results = cal_zero_order_corr_for_tiss(primary_values, target_values)
+        mock_tiss_corr_computation.assert_called_once_with(
+            primary_values=primary_values, target_values=target_values,
+            corr_method="pearson")
+
+        self.assertEqual(len(results), 3)
+
+    @mock.patch("wqflask.correlation.correlation_functions.MrnaAssayTissueData")
+    def test_get_trait_symbol_and_tissue_values(self, mock_class):
+        """test for getting trait symbol and tissue_values"""
+        mock_class_instance = mock_class.return_value
+        mock_class_instance.gene_symbols = ["k1", "k2", "k3"]
+        mock_class_instance.get_symbol_values_pairs.return_value = {
+            "k1": ["v1", "v2", "v3"], "k2": ["v2", "v3"], "k3": ["k3"]}
+        results = get_trait_symbol_and_tissue_values(
+            symbol_list=["k1", "k2", "k3"])
+        mock_class.assert_called_with(gene_symbols=['k1', 'k2', 'k3'])
+        self.assertEqual({"k1": ["v1", "v2", "v3"], "k2": [
+                         "v2", "v3"], "k3": ["k3"]}, results)
diff --git a/wqflask/tests/unit/wqflask/correlation/test_correlation_gn3.py b/wqflask/tests/unit/wqflask/correlation/test_correlation_gn3.py
new file mode 100644
index 00000000..e1bd6d86
--- /dev/null
+++ b/wqflask/tests/unit/wqflask/correlation/test_correlation_gn3.py
@@ -0,0 +1,14 @@
+"""this module contains tests for code used in integrating to gn3 api"""
+from unittest import TestCase
+from base.data_set import create_dataset
+
+class TestCorrelation(TestCase):
+
+    def test_create_dataset(self):
+        """test for creating datasets"""
+
+        pass
+    def test_fetch_dataset_info(self):
+        """test for fetching dataset info data"""
+
+        pass
diff --git a/wqflask/tests/unit/wqflask/correlation/test_show_corr_results.py b/wqflask/tests/unit/wqflask/correlation/test_show_corr_results.py
new file mode 100644
index 00000000..33601990
--- /dev/null
+++ b/wqflask/tests/unit/wqflask/correlation/test_show_corr_results.py
@@ -0,0 +1,98 @@
+import unittest
+from unittest import mock
+from wqflask.correlation.show_corr_results import get_header_fields
+from wqflask.correlation.show_corr_results import generate_corr_json
+
+
+class AttributeSetter:
+    def __init__(self, trait_obj):
+        for key, value in trait_obj.items():
+            setattr(self, key, value)
+
+
+class TestShowCorrResults(unittest.TestCase):
+    def test_get_header_fields(self):
+        expected = [
+            ['Index',
+             'Record',
+             'Symbol',
+             'Description',
+             'Location',
+             'Mean',
+             'Sample rho',
+             'N',
+             'Sample p(rho)',
+             'Lit rho',
+             'Tissue rho',
+             'Tissue p(rho)',
+             'Max LRS',
+             'Max LRS Location',
+             'Additive Effect'],
+
+            ['Index',
+             'ID',
+             'Location',
+             'Sample r',
+             'N',
+             'Sample p(r)']
+
+        ]
+        result1 = get_header_fields("ProbeSet", "spearman")
+        result2 = get_header_fields("Other", "Other")
+        self.assertEqual(result1, expected[0])
+        self.assertEqual(result2, expected[1])
+
+    @mock.patch("wqflask.correlation.show_corr_results.hmac.data_hmac")
+    def test_generate_corr_json(self, mock_data_hmac):
+        mock_data_hmac.return_value = "hajsdiau"
+
+        dataset = AttributeSetter({"name": "the_name"})
+        this_trait = AttributeSetter(
+            {"name": "trait_test", "dataset": dataset})
+        target_dataset = AttributeSetter({"type": "Publish"})
+        corr_trait_1 = AttributeSetter({
+            "name": "trait_1",
+            "dataset": AttributeSetter({"name": "dataset_1"}),
+            "view": True,
+            "abbreviation": "T1",
+            "description_display": "Trait I description",
+            "authors": "JM J,JYEW",
+            "pubmed_id": "34n4nn31hn43",
+            "pubmed_text": "2016",
+            "pubmed_link": "https://www.load",
+            "lod_score": "",
+            "mean": "",
+            "LRS_location_repr": "BXBS",
+            "additive": "",
+            "sample_r": 10.5,
+            "num_overlap": 2,
+            "sample_p": 5
+
+
+
+
+        })
+        corr_results = [corr_trait_1]
+
+        dataset_type_other = {
+            "location": "cx-3-4",
+            "sample_4": 12.32,
+            "num_overlap": 3,
+            "sample_p": 10.34
+        }
+
+        expected_results = '[{"index": 1, "trait_id": "trait_1", "dataset": "dataset_1", "hmac": "hajsdiau", "abbreviation_display": "T1", "description": "Trait I description", "mean": "N/A", "authors_display": "JM J,JYEW", "additive": "N/A", "pubmed_id": "34n4nn31hn43", "year": "2016", "lod_score": "N/A", "lrs_location": "BXBS", "sample_r": "10.500", "num_overlap": 2, "sample_p": "5.000e+00"}]'
+
+        results1 = generate_corr_json(corr_results=corr_results, this_trait=this_trait,
+                                      dataset=dataset, target_dataset=target_dataset, for_api=True)
+        self.assertEqual(expected_results, results1)
+
+    def test_generate_corr_json_view_false(self):
+        trait = AttributeSetter({"view": False})
+        corr_results = [trait]
+        this_trait = AttributeSetter({"name": "trait_test"})
+        dataset = AttributeSetter({"name": "the_name"})
+
+        results_where_view_is_false = generate_corr_json(
+            corr_results=corr_results, this_trait=this_trait, dataset={}, target_dataset={}, for_api=False)
+        self.assertEqual(results_where_view_is_false, "[]")
diff --git a/wqflask/tests/unit/wqflask/marker_regression/__init__.py b/wqflask/tests/unit/wqflask/marker_regression/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/wqflask/tests/unit/wqflask/marker_regression/__init__.py
diff --git a/wqflask/tests/unit/wqflask/marker_regression/test_display_mapping_results.py b/wqflask/tests/unit/wqflask/marker_regression/test_display_mapping_results.py
new file mode 100644
index 00000000..f4869c45
--- /dev/null
+++ b/wqflask/tests/unit/wqflask/marker_regression/test_display_mapping_results.py
@@ -0,0 +1,159 @@
+import unittest
+
+import htmlgen as HT
+from wqflask.marker_regression.display_mapping_results import (
+    DisplayMappingResults,
+    HtmlGenWrapper
+)
+
+
+class TestDisplayMappingResults(unittest.TestCase):
+    """Basic Methods to test Mapping Results"""
+
+    def test_pil_colors(self):
+        """Test that colors use PILLOW color format"""
+        self.assertEqual(DisplayMappingResults.CLICKABLE_WEBQTL_REGION_COLOR,
+                         (245, 211, 211))
+
+
+class TestHtmlGenWrapper(unittest.TestCase):
+    """Test Wrapper around HTMLGen"""
+
+    def test_create_image(self):
+        """Test HT.Image method"""
+        self.assertEqual(
+            str(HtmlGenWrapper.create_image_tag(src="test.png",
+                                                alt="random",
+                                                border="0",
+                                                width="10",
+                                                height="13",
+                                                usemap="#webqtlmap")),
+            ("""<img alt="random" border="0" height="13" """
+             """src="test.png" usemap="#webqtlmap" """
+             """width="10"/>""")
+        )
+
+    def test_create_form(self):
+        """Test HT.Form method"""
+        test_form = HtmlGenWrapper.create_form_tag(
+            cgi="/testing/",
+            enctype='multipart/form-data',
+            name="formName",
+            submit=HtmlGenWrapper.create_input_tag(
+                type_='hidden', name='Default_Name')
+        )
+        test_image = HtmlGenWrapper.create_image_tag(
+            src="test.png",
+            alt="random",
+            border="0",
+            width="10",
+            height="13",
+            usemap="#webqtlmap"
+        )
+        self.assertEqual(
+            str(test_form).replace("\n", ""),
+            ("""<form action="/testing/" enctype="multipart/form-data" """
+             """method="POST" """
+             """name="formName"><input name="Default_Name" """
+             """type="hidden"/></form>"""))
+        hddn = {
+            'FormID': 'showDatabase',
+            'ProbeSetID': '_',
+            'database': "TestGeno",
+            'CellID': '_',
+            'RISet': "Test",
+            'incparentsf1': 'ON'
+        }
+        for key in hddn.keys():
+            test_form.append(
+                HtmlGenWrapper.create_input_tag(
+                    name=key,
+                    value=hddn[key],
+                    type_='hidden'))
+        test_form.append(test_image)
+
+        self.assertEqual(str(test_form).replace("\n", ""), (
+            """<form action="/testing/" enctype="multipart/form-data" """
+            """method="POST" name="formName">"""
+            """<input name="Default_Name" type="hidden"/>"""
+            """<input name="FormID" type="hidden" value="showDatabase"/>"""
+            """<input name="ProbeSetID" type="hidden" value="_"/>"""
+            """<input name="database" type="hidden" value="TestGeno"/>"""
+            """<input name="CellID" type="hidden" value="_"/>"""
+            """<input name="RISet" type="hidden" value="Test"/>"""
+            """<input name="incparentsf1" type="hidden" value="ON"/>"""
+            """<img alt="random" border="0" height="13" src="test.png" """
+            """usemap="#webqtlmap" width="10"/>"""
+            """</form>"""))
+
+    def test_create_paragraph(self):
+        """Test HT.Paragraph method"""
+        test_p_element = HtmlGenWrapper.create_p_tag(id="smallSize")
+        par_text = (
+            "Mapping using genotype data as "
+            "a trait will result in infinity LRS at one locus. "
+            "In order to display the result properly, all LRSs "
+            "higher than 100 are capped at 100."
+        )
+        self.assertEqual(
+            str(test_p_element),
+            """<p id="smallSize"></p>"""
+        )
+        test_p_element.append(HtmlGenWrapper.create_br_tag())
+        test_p_element.append(par_text)
+        self.assertEqual(
+            str(test_p_element),
+            """<p id="smallSize"><br/>{}</p>""".format(par_text)
+        )
+
+    def test_create_br_tag(self):
+        """Test HT.BR() method"""
+        self.assertEqual(str(HtmlGenWrapper.create_br_tag()),
+                         "<br/>")
+
+    def test_create_input_tag(self):
+        """Test HT.Input method"""
+        self.assertEqual(
+            str(HtmlGenWrapper.create_input_tag(
+                type_="hidden",
+                name="name",
+                value="key",
+                Class="trait trait_")).replace("\n", ""),
+            ("""<input class="trait trait_" name="name" """
+             """type="hidden" value="key"/>"""))
+
+    def test_create_map_tag(self):
+        """Test HT.Map method"""
+        self.assertEqual(str(HtmlGenWrapper.create_map_tag(
+            name="WebqTLImageMap")).replace("\n", ""),
+            """<map name="WebqTLImageMap"></map>""")
+        gifmap = HtmlGenWrapper.create_map_tag(name="test")
+        gifmap.append(HtmlGenWrapper.create_area_tag(shape="rect",
+                                                     coords='1 2 3', href='#area1'))
+        gifmap.append(HtmlGenWrapper.create_area_tag(shape="rect",
+                                                     coords='1 2 3', href='#area2'))
+        self.assertEqual(
+            str(gifmap).replace("\n", ""),
+            ("""<map name="test">"""
+             """<area coords="1 2 3" """
+             """href="#area1" shape="rect"/>"""
+             """<area coords="1 2 3" href="#area2" shape="rect"/>"""
+             """</map>"""))
+
+    def test_create_area_tag(self):
+        """Test HT.Area method"""
+        self.assertEqual(
+            str(HtmlGenWrapper.create_area_tag(
+                shape="rect",
+                coords="1 2",
+                href="http://test.com",
+                title="Some Title")).replace("\n", ""),
+            ("""<area coords="1 2" href="http://test.com" """
+             """shape="rect" title="Some Title"/>"""))
+
+    def test_create_link_tag(self):
+        """Test HT.HREF method"""
+        self.assertEqual(
+            str(HtmlGenWrapper.create_link_tag(
+                "www.test.com", "test", target="_blank")).replace("\n", ""),
+            """<a href="www.test.com" target="_blank">test</a>""")
diff --git a/wqflask/tests/unit/wqflask/marker_regression/test_gemma_mapping.py b/wqflask/tests/unit/wqflask/marker_regression/test_gemma_mapping.py
new file mode 100644
index 00000000..58a44b2a
--- /dev/null
+++ b/wqflask/tests/unit/wqflask/marker_regression/test_gemma_mapping.py
@@ -0,0 +1,188 @@
+# test for wqflask/marker_regression/gemma_mapping.py
+import unittest
+import random
+from unittest import mock
+from wqflask.marker_regression.gemma_mapping import run_gemma
+from wqflask.marker_regression.gemma_mapping import gen_pheno_txt_file
+from wqflask.marker_regression.gemma_mapping import gen_covariates_file
+from wqflask.marker_regression.gemma_mapping import parse_loco_output
+
+
+class AttributeSetter:
+    def __init__(self, obj):
+        for key, val in obj.items():
+            setattr(self, key, val)
+
+
+class MockGroup(AttributeSetter):
+    def get_samplelist(self):
+        return None
+
+
+class TestGemmaMapping(unittest.TestCase):
+
+    @mock.patch("wqflask.marker_regression.gemma_mapping.parse_loco_output")
+    def test_run_gemma_firstrun_set_false(self, mock_parse_loco):
+        """add tests for gemma function where  first run is set to false"""
+        dataset = AttributeSetter(
+            {"group": AttributeSetter({"genofile": "genofile.geno"})})
+
+        output_file = "file1"
+        mock_parse_loco.return_value = []
+        this_trait = AttributeSetter({"name": "t1"})
+
+        result = run_gemma(this_trait=this_trait, this_dataset=dataset, samples=[], vals=[
+        ], covariates="", use_loco=True, first_run=False, output_files=output_file)
+
+        expected_results = ([], "file1")
+        self.assertEqual(expected_results, result)
+
+    @mock.patch("wqflask.marker_regression.gemma_mapping.webqtlConfig.GENERATED_IMAGE_DIR", "/home/user/img")
+    @mock.patch("wqflask.marker_regression.gemma_mapping.GEMMAOPTS", "-debug")
+    @mock.patch("wqflask.marker_regression.gemma_mapping.GEMMA_WRAPPER_COMMAND", "ghc")
+    @mock.patch("wqflask.marker_regression.gemma_mapping.TEMPDIR", "/home/user/data/")
+    @mock.patch("wqflask.marker_regression.gemma_mapping.parse_loco_output")
+    @mock.patch("wqflask.marker_regression.gemma_mapping.flat_files")
+    @mock.patch("wqflask.marker_regression.gemma_mapping.gen_covariates_file")
+    @mock.patch("wqflask.marker_regression.run_mapping.random.choice")
+    @mock.patch("wqflask.marker_regression.gemma_mapping.os")
+    @mock.patch("wqflask.marker_regression.gemma_mapping.gen_pheno_txt_file")
+    def test_run_gemma_firstrun_set_true(self, mock_gen_pheno_txt, mock_os, mock_choice, mock_gen_covar, mock_flat_files, mock_parse_loco):
+        """add tests for run_gemma where first run is set to true"""
+        this_chromosomes = {}
+        for i in range(1, 5):
+            this_chromosomes[f'CH{i}'] = (AttributeSetter({"name": f"CH{i}"}))
+        chromosomes = AttributeSetter({"chromosomes": this_chromosomes})
+
+        dataset_group = MockGroup(
+            {"name": "GP1", "genofile": "file_geno"})
+        dataset = AttributeSetter({"group": dataset_group, "name": "dataset1_name",
+                                   "species": AttributeSetter({"chromosomes": chromosomes})})
+        trait = AttributeSetter({"name": "trait1"})
+        samples = []
+        mock_gen_pheno_txt.return_value = None
+        mock_os.path.isfile.return_value = True
+        mock_gen_covar.return_value = None
+        mock_choice.return_value = "R"
+        mock_flat_files.return_value = "/home/genotype/bimbam"
+        mock_parse_loco.return_value = []
+        results = run_gemma(this_trait=trait, this_dataset=dataset, samples=[
+        ], vals=[], covariates="", use_loco=True)
+        self.assertEqual(mock_os.system.call_count, 2)
+        mock_gen_pheno_txt.assert_called_once()
+        mock_parse_loco.assert_called_once_with(
+            dataset, "GP1_GWA_RRRRRR", True)
+        mock_os.path.isfile.assert_called_once_with(
+            ('/home/user/imgfile_output.assoc.txt'))
+        self.assertEqual(mock_flat_files.call_count, 4)
+        self.assertEqual(results, ([], "GP1_GWA_RRRRRR"))
+
+    @mock.patch("wqflask.marker_regression.gemma_mapping.TEMPDIR", "/home/user/data")
+    def test_gen_pheno_txt_file(self):
+        """add tests for generating pheno txt file"""
+        with mock.patch("builtins.open", mock.mock_open())as mock_open:
+            gen_pheno_txt_file(
+                this_dataset=AttributeSetter({"name": "A"}),
+                genofile_name="", vals=[
+                    "x", "w", "q", "we", "R"])
+            mock_open.assert_called_once_with(
+                '/home/user/data/gn2/PHENO_KiAEKlCvM6iGTM9Kh_TAlQ.txt', 'w')
+            filehandler = mock_open()
+            values = ["x", "w", "q", "we", "R"]
+            write_calls = [mock.call('NA\n'), mock.call('w\n'), mock.call(
+                'q\n'), mock.call('we\n'), mock.call('R\n')]
+
+            filehandler.write.assert_has_calls(write_calls)
+
+    @mock.patch("wqflask.marker_regression.gemma_mapping.flat_files")
+    @mock.patch("wqflask.marker_regression.gemma_mapping.create_trait")
+    @mock.patch("wqflask.marker_regression.gemma_mapping.create_dataset")
+    def test_gen_covariates_file(self, create_dataset, create_trait, flat_files):
+        """add tests for generating covariates files"""
+        covariates = "X1:X2,Y1:Y2,M1:M3,V1:V2"
+        samplelist = ["X1", "X2", "X3", "X4"]
+        create_dataset_side_effect = []
+        create_trait_side_effect = []
+
+        for i in range(4):
+            create_dataset_side_effect.append(
+                AttributeSetter({"name": f'name_{i}'}))
+            create_trait_side_effect.append(
+                AttributeSetter({"data": [f'data_{i}']}))
+
+        create_dataset.side_effect = create_trait_side_effect
+        create_trait.side_effect = create_trait_side_effect
+
+        group = MockGroup({"name": "group_X", "samplelist": samplelist})
+        this_dataset = AttributeSetter({"group": group, "name": "A"})
+        flat_files.return_value = "Home/Genenetwork"
+
+        with mock.patch("builtins.open", mock.mock_open())as mock_open:
+            gen_covariates_file(this_dataset=this_dataset, covariates=covariates,
+                                samples=["x1", "x2", "X3"])
+
+            create_dataset.assert_has_calls(
+                [mock.call('X2'), mock.call('Y2'), mock.call('M3'), mock.call('V2')])
+            mock_calls = []
+            trait_names = ["X1", "Y1", "M1", "V1"]
+
+            for i, trait in enumerate(create_trait_side_effect):
+                mock_calls.append(
+                    mock.call(dataset=trait, name=trait_names[i], cellid=None))
+
+            create_trait.assert_has_calls(mock_calls)
+
+            flat_files.assert_called_once_with('mapping')
+            mock_open.assert_called_once_with(
+                'Home/Genenetwork/COVAR_anFZ_LfZYV0Ulywo+7tRCw.txt', 'w')
+            filehandler = mock_open()
+            filehandler.write.assert_has_calls([mock.call(
+                '-9\t'), mock.call('-9\t'), mock.call('-9\t'), mock.call('-9\t'), mock.call('\n')])
+
+    @mock.patch("wqflask.marker_regression.gemma_mapping.TEMPDIR", "/home/tmp")
+    @mock.patch("wqflask.marker_regression.gemma_mapping.os")
+    @mock.patch("wqflask.marker_regression.gemma_mapping.json")
+    def test_parse_loco_outputfile_found(self, mock_json, mock_os):
+        """add tests for parse loco output file found"""
+        mock_json.load.return_value = {
+            "files": [["file_name", "user", "~/file1"],
+                      ["file_name", "user", "~/file2"]]
+        }
+        return_file = """X/Y\tM1\t28.457155\tQ\tE\tA\tMMB\t23.3\tW\t0.9\t0.85\t
+chr4\tM2\t12\tQ\tE\tMMB\tR\t24\tW\t0.87\t0.5
+Y\tM4\t12\tQ\tE\tMMB\tR\t11.6\tW\t0.21\t0.7
+X\tM5\t12\tQ\tE\tMMB\tR\t21.1\tW\t0.65\t0.6"""
+
+        return_file_2 = """chr\tother\t21322\tQ\tE\tA\tP\tMMB\tCDE\t0.5\t0.4"""
+        mock_os.path.isfile.return_value = True
+        file_to_write = """{"files":["file_1","file_2"]}"""
+        with mock.patch("builtins.open") as mock_open:
+
+            handles = (mock.mock_open(read_data="gwas").return_value, mock.mock_open(
+                read_data=return_file).return_value, mock.mock_open(read_data=return_file_2).return_value)
+            mock_open.side_effect = handles
+            results = parse_loco_output(
+                this_dataset={}, gwa_output_filename=".xw/")
+            expected_results = [
+                {'name': 'M1', 'chr': 'X/Y', 'Mb': 2.8457155e-05, 'p_value': 0.85,
+                 'additive': 23.3, 'lod_score': 0.07058107428570727},
+                {'name': 'M2', 'chr': 4, 'Mb': 1.2e-05, 'p_value': 0.5,
+                 'additive': 24.0, 'lod_score': 0.3010299956639812},
+                {'name': 'M4', 'chr': 'Y', 'Mb': 1.2e-05, 'p_value': 0.7,
+                 'additive': 11.6, 'lod_score': 0.1549019599857432},
+                {'name': 'M5', 'chr': 'X', 'Mb': 1.2e-05, 'p_value': 0.6, 'additive': 21.1, 'lod_score': 0.22184874961635637}]
+
+            self.assertEqual(expected_results, results)
+
+    @mock.patch("wqflask.marker_regression.gemma_mapping.TEMPDIR", "/home/tmp")
+    @mock.patch("wqflask.marker_regression.gemma_mapping.os")
+    def test_parse_loco_outputfile_not_found(self, mock_os):
+        """add tests for parse loco output where  output file not found"""
+
+        mock_os.path.isfile.return_value = False
+        file_to_write = """{"files":["file_1","file_2"]}"""
+
+        with mock.patch("builtins.open", mock.mock_open(read_data=file_to_write)) as mock_open:
+            results = parse_loco_output(
+                this_dataset={}, gwa_output_filename=".xw/")
+            self.assertEqual(results, [])
diff --git a/wqflask/tests/unit/wqflask/marker_regression/test_plink_mapping.py b/wqflask/tests/unit/wqflask/marker_regression/test_plink_mapping.py
new file mode 100644
index 00000000..fd21a825
--- /dev/null
+++ b/wqflask/tests/unit/wqflask/marker_regression/test_plink_mapping.py
@@ -0,0 +1,86 @@
+# test for wqflask/marker_regression/plink_mapping.py
+import unittest
+from unittest import mock
+from wqflask.marker_regression.plink_mapping import build_line_list
+from wqflask.marker_regression.plink_mapping import get_samples_from_ped_file
+from wqflask.marker_regression.plink_mapping import flat_files
+from wqflask.marker_regression.plink_mapping import gen_pheno_txt_file_plink
+from wqflask.marker_regression.plink_mapping import parse_plink_output
+
+
+class AttributeSetter:
+    def __init__(self, obj):
+        for key, val in obj.items():
+            setattr(self, key, val)
+
+
+class TestPlinkMapping(unittest.TestCase):
+
+    def test_build_line_list(self):
+        """test for building line list"""
+        line_1 = "this is line one test"
+        irregular_line = "  this     is an, irregular line     "
+        exp_line1 = ["this", "is", "line", "one", "test"]
+
+        results = build_line_list(irregular_line)
+        self.assertEqual(exp_line1, build_line_list(line_1))
+        self.assertEqual([], build_line_list())
+        self.assertEqual(["this", "is", "an,", "irregular", "line"], results)
+
+    @mock.patch("wqflask.marker_regression.plink_mapping.flat_files")
+    def test_get_samples_from_ped_file(self, mock_flat_files):
+        """test for getting samples from ped file"""
+        dataset = AttributeSetter({"group": AttributeSetter({"name": "n_1"})})
+        file_sample = """Expected_1\tline test
+Expected_2\there
+  Expected_3\tthree"""
+        mock_flat_files.return_value = "/home/user/"
+        with mock.patch("builtins.open", mock.mock_open(read_data=file_sample)) as mock_open:
+            results = get_samples_from_ped_file(dataset)
+            mock_flat_files.assert_called_once_with("mapping")
+            mock_open.assert_called_once_with("/home/user/n_1.ped", "r")
+            self.assertEqual(
+                ["Expected_1", "Expected_2", "Expected_3"], results)
+
+    @mock.patch("wqflask.marker_regression.plink_mapping.TMPDIR", "/home/user/data/")
+    @mock.patch("wqflask.marker_regression.plink_mapping.get_samples_from_ped_file")
+    def test_gen_pheno_txt_file_plink(self, mock_samples):
+        """test for getting gen_pheno txt file"""
+        mock_samples.return_value = ["Expected_1", "Expected_2", "Expected_3"]
+
+        trait = AttributeSetter({"name": "TX"})
+        dataset = AttributeSetter({"group": AttributeSetter({"name": "n_1"})})
+        vals = ["value=K1", "value=K2", "value=K3"]
+        with mock.patch("builtins.open", mock.mock_open()) as mock_open:
+            results = gen_pheno_txt_file_plink(this_trait=trait, dataset=dataset,
+                                               vals=vals, pheno_filename="ph_file")
+            mock_open.assert_called_once_with(
+                "/home/user/data/ph_file.txt", "wb")
+            filehandler = mock_open()
+            calls_expected = [mock.call('FID\tIID\tTX\n'),
+                              mock.call('Expected_1\tExpected_1\tK1\nExpected_2\tExpected_2\tK2\nExpected_3\tExpected_3\tK3\n')]
+
+            filehandler.write.assert_has_calls(calls_expected)
+
+            filehandler.close.assert_called_once()
+
+    @mock.patch("wqflask.marker_regression.plink_mapping.TMPDIR", "/home/user/data/")
+    @mock.patch("wqflask.marker_regression.plink_mapping.build_line_list")
+    def test_parse_plink_output(self, mock_line_list):
+        """test for parsing plink output"""
+        chromosomes = [0, 34, 110, 89, 123, 23, 2]
+        species = AttributeSetter(
+            {"name": "S1", "chromosomes": AttributeSetter({"chromosomes": chromosomes})})
+
+        fake_file = """0 AACCAT T98.6  0.89\n2  AATA  B45  0.3\n121  ACG  B56.4 NA"""
+
+        mock_line_list.side_effect = [["0", "AACCAT", "T98.6", "0.89"], [
+            "2", "AATA", "B45", "0.3"], ["121", "ACG", "B56.4", "NA"]]
+        with mock.patch("builtins.open", mock.mock_open(read_data=fake_file)) as mock_open:
+            parse_results = parse_plink_output(
+                output_filename="P1_file", species=species)
+            mock_open.assert_called_once_with(
+                "/home/user/data/P1_file.qassoc", "rb")
+            expected = (2, {'AACCAT': 0.89, 'AATA': 0.3})
+
+            self.assertEqual(parse_results, expected)
diff --git a/wqflask/tests/unit/wqflask/marker_regression/test_qtlreaper_mapping.py b/wqflask/tests/unit/wqflask/marker_regression/test_qtlreaper_mapping.py
new file mode 100644
index 00000000..8b4337ec
--- /dev/null
+++ b/wqflask/tests/unit/wqflask/marker_regression/test_qtlreaper_mapping.py
@@ -0,0 +1,24 @@
+import unittest
+from unittest import mock
+from wqflask.marker_regression.qtlreaper_mapping import gen_pheno_txt_file
+
+# issues some methods in genofile object are not defined
+# modify samples should equal to vals
+
+
+class TestQtlReaperMapping(unittest.TestCase):
+    @mock.patch("wqflask.marker_regression.qtlreaper_mapping.TEMPDIR", "/home/user/data")
+    def test_gen_pheno_txt_file(self):
+        vals = ["V1", "x", "V4", "V3", "x"]
+        samples = ["S1", "S2", "S3", "S4", "S5"]
+        trait_filename = "trait_file"
+        with mock.patch("builtins.open", mock.mock_open())as mock_open:
+            gen_pheno_txt_file(samples=samples, vals=vals,
+                               trait_filename=trait_filename)
+            mock_open.assert_called_once_with(
+                "/home/user/data/gn2/trait_file.txt", "w")
+            filehandler = mock_open()
+            write_calls = [mock.call('Trait\t'), mock.call(
+                'S1\tS3\tS4\n'), mock.call('T1\t'), mock.call('V1\tV4\tV3')]
+
+            filehandler.write.assert_has_calls(write_calls)
diff --git a/wqflask/tests/unit/wqflask/marker_regression/test_rqtl_mapping.py b/wqflask/tests/unit/wqflask/marker_regression/test_rqtl_mapping.py
new file mode 100644
index 00000000..9d13e943
--- /dev/null
+++ b/wqflask/tests/unit/wqflask/marker_regression/test_rqtl_mapping.py
@@ -0,0 +1,43 @@
+import unittest
+from unittest import mock
+from dataclasses import dataclass
+
+from wqflask.marker_regression.rqtl_mapping import run_rqtl
+
+@dataclass
+class MockGroup:
+    name: str
+    genofile: str
+
+@dataclass
+class MockDataset:
+    group: MockGroup
+
+class TestRqtlMapping(unittest.TestCase):
+    """Tests for functions in rqtl_mapping.py"""
+    @mock.patch("wqflask.marker_regression.rqtl_mapping.requests.post")
+    @mock.patch("wqflask.marker_regression.rqtl_mapping.locate")
+    @mock.patch("wqflask.marker_regression.rqtl_mapping.write_phenotype_file")
+    def test_run_rqtl_with_perm(self, mock_write_pheno_file, mock_locate, mock_post):
+        """Test for run_rqtl with permutations > 0"""
+        dataset_group = MockGroup("GP1", "file_geno")
+        dataset = MockDataset(dataset_group)
+
+        mock_write_pheno_file.return_value = "pheno_filename"
+        mock_locate.return_value = "geno_filename"
+        mock_post.return_value = mock.Mock(ok=True)
+        mock_post.return_value.json.return_value = {"perm_results": [],
+                                                    "suggestive": 3,
+                                                    "significant": 4,
+                                                    "results" : []}
+
+        results = run_rqtl(trait_name="the_trait", vals=[], samples=[],
+        dataset=dataset, mapping_scale="cM", model="normal", method="hk",
+        num_perm=5, perm_strata_list=[], do_control="false", control_marker="",
+        manhattan_plot=True, cofactors="")
+
+        mock_write_pheno_file.assert_called_once()
+        mock_locate.assert_called_once()
+        mock_post.assert_called_once()
+
+        self.assertEqual(results, ([], 3, 4, []))
diff --git a/wqflask/tests/unit/wqflask/marker_regression/test_run_mapping.py b/wqflask/tests/unit/wqflask/marker_regression/test_run_mapping.py
new file mode 100644
index 00000000..868b0b0b
--- /dev/null
+++ b/wqflask/tests/unit/wqflask/marker_regression/test_run_mapping.py
@@ -0,0 +1,287 @@
+import unittest
+import datetime
+from unittest import mock
+
+from wqflask.marker_regression.run_mapping import get_genofile_samplelist
+from wqflask.marker_regression.run_mapping import geno_db_exists
+from wqflask.marker_regression.run_mapping import write_input_for_browser
+from wqflask.marker_regression.run_mapping import export_mapping_results
+from wqflask.marker_regression.run_mapping import trim_markers_for_figure
+from wqflask.marker_regression.run_mapping import get_perm_strata
+from wqflask.marker_regression.run_mapping import get_chr_lengths
+
+
+class AttributeSetter:
+    def __init__(self, obj):
+        for k, v in obj.items():
+            setattr(self, k, v)
+
+
+class MockGroup(AttributeSetter):
+
+    def get_genofiles(self):
+        return [{"location": "~/genofiles/g1_file", "sample_list": ["S1", "S2", "S3", "S4"]}]
+
+
+class TestRunMapping(unittest.TestCase):
+    def setUp(self):
+
+        self.group = MockGroup(
+            {"genofile": "~/genofiles/g1_file", "name": "GP1_", "species": "Human"})
+        chromosomes = {
+            "3": AttributeSetter({
+                "name": "C1",
+                "length": "0.04"
+            }),
+            "4": AttributeSetter({
+                "name": "C2",
+                "length": "0.03"
+            }),
+            "5": AttributeSetter({
+                "name": "C4",
+                "length": "0.01"
+            })
+        }
+        self.dataset = AttributeSetter(
+            {"fullname": "dataset_1", "group": self.group, "type": "ProbeSet"})
+
+        self.chromosomes = AttributeSetter({"chromosomes": chromosomes})
+        self.trait = AttributeSetter(
+            {"symbol": "IGFI", "chr": "X1", "mb": 123313, "display_name": "Test Name"})
+
+    def tearDown(self):
+        self.dataset = AttributeSetter(
+            {"group": {"location": "~/genofiles/g1_file"}})
+
+    def test_get_genofile_samplelist(self):
+
+        results_1 = get_genofile_samplelist(self.dataset)
+        self.assertEqual(results_1, ["S1", "S2", "S3", "S4"])
+        self.group.genofile = "~/genofiles/g2_file"
+        result_2 = get_genofile_samplelist(self.dataset)
+        self.assertEqual(result_2, [])
+
+    @mock.patch("wqflask.marker_regression.run_mapping.data_set")
+    def test_if_geno_db_exists(self, mock_data_set):
+        mock_data_set.create_dataset.side_effect = [
+            AttributeSetter({}), Exception()]
+        results_no_error = geno_db_exists(self.dataset)
+        results_with_error = geno_db_exists(self.dataset)
+
+        self.assertEqual(mock_data_set.create_dataset.call_count, 2)
+        self.assertEqual(results_with_error, "False")
+        self.assertEqual(results_no_error, "True")
+
+    def test_trim_markers_for_figure(self):
+
+        markers = [{
+            "name": "MK1",
+            "chr": "C1",
+            "cM": "1",
+            "Mb": "12000",
+            "genotypes": [],
+            "dominance":"TT",
+            "additive":"VA",
+            "lod_score":0.5
+        },
+            {
+            "name": "MK2",
+            "chr": "C2",
+            "cM": "15",
+            "Mb": "10000",
+            "genotypes": [],
+            "lod_score":0.7
+        },
+            {
+            "name": "MK1",
+            "chr": "C3",
+            "cM": "45",
+            "Mb": "1",
+            "genotypes": [],
+            "dominance":"Tt",
+            "additive":"VE",
+            "lod_score":1
+        }]
+
+        marker_2 = [{
+            "name": "MK1",
+            "chr": "C1",
+            "cM": "1",
+            "Mb": "12000",
+            "genotypes": [],
+            "dominance":"TT",
+            "additive":"VA",
+            "p_wald":4.6
+        }]
+        results = trim_markers_for_figure(markers)
+        result_2 = trim_markers_for_figure(marker_2)
+        expected = [
+            {
+                "name": "MK1",
+                "chr": "C1",
+                "cM": "1",
+                "Mb": "12000",
+                "genotypes": [],
+                "dominance":"TT",
+                "additive":"VA",
+                "lod_score":0.5
+            },
+            {
+                "name": "MK1",
+                "chr": "C3",
+                "cM": "45",
+                "Mb": "1",
+                "genotypes": [],
+                "dominance":"Tt",
+                "additive":"VE",
+                "lod_score":1
+            }
+
+        ]
+        self.assertEqual(results, expected)
+        self.assertEqual(result_2, marker_2)
+
+    def test_export_mapping_results(self):
+        """test for exporting mapping results"""
+        datetime_mock = mock.Mock(wraps=datetime.datetime)
+        datetime_mock.now.return_value = datetime.datetime(
+            2019, 9, 1, 10, 12, 12)
+
+        markers = [{
+            "name": "MK1",
+            "chr": "C1",
+            "cM": "1",
+            "Mb": "12000",
+            "genotypes": [],
+            "dominance":"TT",
+            "additive":"VA",
+            "lod_score":3
+        },
+            {
+            "name": "MK2",
+            "chr": "C2",
+            "cM": "15",
+            "Mb": "10000",
+            "genotypes": [],
+            "lod_score":7
+        },
+            {
+            "name": "MK1",
+            "chr": "C3",
+            "cM": "45",
+            "Mb": "1",
+            "genotypes": [],
+            "dominance":"Tt",
+            "additive":"VE",
+            "lod_score":7
+        }]
+
+        with mock.patch("builtins.open", mock.mock_open()) as mock_open:
+
+            with mock.patch("wqflask.marker_regression.run_mapping.datetime.datetime", new=datetime_mock):
+                export_mapping_results(dataset=self.dataset, trait=self.trait, markers=markers,
+                                       results_path="~/results", mapping_method="gemma", mapping_scale="physic",
+                                       score_type="-logP", transform="qnorm",
+                                       covariates="Dataset1:Trait1,Dataset2:Trait2",
+                                       n_samples="100", vals_hash="")
+
+                write_calls = [
+                    mock.call('Time/Date: 09/01/19 / 10:12:12\n'),
+                    mock.call('Population: Human GP1_\n'), mock.call(
+                        'Data Set: dataset_1\n'),
+                    mock.call('Trait: Test Name\n'),
+                    mock.call('Trait Hash: \n'),
+                    mock.call('N Samples: 100\n'),
+                    mock.call('Mapping Tool: gemma\n'),
+                    mock.call('Transform - Quantile Normalized\n'),
+                    mock.call('Gene Symbol: IGFI\n'), mock.call(
+                        'Location: X1 @ 123313 Mb\n'),
+                    mock.call('Cofactors (dataset - trait):\n'),
+                    mock.call('Trait1 - Dataset1\n'),
+                    mock.call('Trait2 - Dataset2\n'),
+                    mock.call('\n'), mock.call('Name,Chr,'),
+                    mock.call('Mb,-logP'),
+                    mock.call(',Additive'), mock.call(',Dominance'),
+                    mock.call('\n'), mock.call('MK1,C1,'),
+                    mock.call('12000,'), mock.call('3'),
+                    mock.call(',VA'), mock.call(',TT'),
+                    mock.call('\n'), mock.call('MK2,C2,'),
+                    mock.call('10000,'), mock.call('7'),
+                    mock.call('\n'), mock.call('MK1,C3,'),
+                    mock.call('1,'), mock.call('7'),
+                    mock.call(',VE'), mock.call(',Tt')
+                ]
+                mock_open.assert_called_once_with("~/results", "w+")
+                filehandler = mock_open()
+                filehandler.write.assert_has_calls(write_calls)
+
+    @mock.patch("wqflask.marker_regression.run_mapping.random.choice")
+    def test_write_input_for_browser(self, mock_choice):
+        """test for writing input for browser"""
+        mock_choice.side_effect = ["F", "i", "l", "e", "s", "x"]
+        with mock.patch("builtins.open", mock.mock_open()) as mock_open:
+            expected = ['GP1__Filesx_GWAS', 'GP1__Filesx_ANNOT']
+
+            results = write_input_for_browser(
+                this_dataset=self.dataset, gwas_results={}, annotations={})
+            self.assertEqual(results, expected)
+
+    def test_get_perm_strata(self):
+        categorical_vars = ["C1", "C2", "W1"]
+        used_samples = ["S1", "S2"]
+        sample_list = AttributeSetter({"sample_attribute_values": {
+            "S1": {
+                "c1": "c1_value",
+                "c2": "c2_value",
+                "w1": "w1_value"
+            },
+            "S2": {
+                "w1": "w2_value",
+                "w2": "w2_value"
+            },
+            "S3": {
+
+                "c1": "c1_value",
+                "c2": "c2_value"
+            },
+        }})
+        results = get_perm_strata(this_trait={}, sample_list=sample_list,
+                                  categorical_vars=categorical_vars, used_samples=used_samples)
+        self.assertEqual(results, [1, 1])
+
+    def test_get_chr_length(self):
+        """test for getting chromosome length"""
+        chromosomes = AttributeSetter({"chromosomes": self.chromosomes})
+        dataset = AttributeSetter({"species": chromosomes})
+        results = get_chr_lengths(
+            mapping_scale="physic", mapping_method="reaper", dataset=dataset, qtl_results=[])
+        chr_lengths = []
+        for key, chromo in self.chromosomes.chromosomes.items():
+            chr_lengths.append({"chr": chromo.name, "size": chromo.length})
+
+        self.assertEqual(chr_lengths, results)
+
+        qtl_results = [{
+            "chr": "16",
+            "cM": "0.2"
+        },
+            {
+            "chr": "12",
+            "cM": "0.5"
+        },
+            {
+            "chr": "18",
+            "cM": "0.1"
+        },
+            {
+            "chr": "22",
+            "cM": "0.4"
+        },
+        ]
+
+        result_with_other_mapping_scale = get_chr_lengths(
+            mapping_scale="other", mapping_method="reaper", dataset=dataset, qtl_results=qtl_results)
+        expected_value = [{'chr': '1', 'size': '0'}, {
+            'chr': '16', 'size': '500000.0'}, {'chr': '18', 'size': '400000.0'}]
+
+        self.assertEqual(result_with_other_mapping_scale, expected_value)
diff --git a/wqflask/tests/unit/wqflask/show_trait/__init__.py b/wqflask/tests/unit/wqflask/show_trait/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/wqflask/tests/unit/wqflask/show_trait/__init__.py
diff --git a/wqflask/tests/unit/wqflask/show_trait/test_export_trait_data.py b/wqflask/tests/unit/wqflask/show_trait/test_export_trait_data.py
new file mode 100644
index 00000000..41761944
--- /dev/null
+++ b/wqflask/tests/unit/wqflask/show_trait/test_export_trait_data.py
@@ -0,0 +1,212 @@
+import unittest
+from unittest import mock
+from wqflask.show_trait.export_trait_data import dict_to_sorted_list
+from wqflask.show_trait.export_trait_data import cmp_samples
+from wqflask.show_trait.export_trait_data import export_sample_table
+from wqflask.show_trait.export_trait_data import get_export_metadata
+
+
+class AttributesSetter:
+    def __init__(self, obj):
+        for key, value in obj.items():
+            setattr(self, key, value)
+
+
+class TestExportTraits(unittest.TestCase):
+    """Test methods related to converting dict to sortedlist"""
+    @mock.patch("wqflask.show_trait.export_trait_data.create_trait")
+    @mock.patch("wqflask.show_trait.export_trait_data.data_set")
+    def test_get_export_metadata_no_publish(self, mock_dataset, mock_trait):
+        """test for exporting metadata with no publish"""
+        mock_dataset_attributes = AttributesSetter(
+            {"type": "no_publish", "dataset_name": "Temp", "name": "Temp"})
+
+        mock_nested_attributes = AttributesSetter({"name": "name"})
+        mock_dataset_attributes.group = mock_nested_attributes
+        mock_dataset.create_dataset.return_value = mock_dataset_attributes
+        mock_trait.return_value = AttributesSetter({"symbol": "", "description_display": "Description",
+                                                    "title": "research1", "journal": "", "authors": ""})
+
+        results = get_export_metadata("random_id", "Temp")
+        expected = [["Record ID: random_id"],
+                    ["Trait URL: http://genenetwork.org/show_trait?trait_id=random_id&dataset=Temp"],
+                    ["Dataset: Temp"],
+                    ["Group: name"], []]
+
+        mock_dataset.create_dataset.assert_called_with("Temp")
+        mock_trait.assert_called_with(
+            dataset=mock_dataset_attributes, name="random_id", cellid=None, get_qtl_info=False)
+        self.assertEqual(results, expected)
+
+    @mock.patch("wqflask.show_trait.export_trait_data.create_trait")
+    @mock.patch("wqflask.show_trait.export_trait_data.data_set")
+    def test_get_export_metadata_with_publish(self, data_mock, trait_mock):
+        """test for exporting metadata with dataset.type=Publish"""
+        mock_dataset_attributes = AttributesSetter({"type": "Publish", "dataset_name": "Temp",
+                                                    "name": "Temp", "description_display": "Description goes here"})
+
+        mock_nested_attributes = AttributesSetter({"name": "name"})
+        mock_dataset_attributes.group = mock_nested_attributes
+        data_mock.create_dataset.return_value = mock_dataset_attributes
+        trait_instance = AttributesSetter({"symbol": "", "description_display": "Description",
+                                           "title": "research1", "journal": "", "authors": ""})
+        trait_mock.return_value = trait_instance
+
+        results = get_export_metadata(
+            "29ae0615-0d77-4814-97c7-c9e91f6bfd7b", "Temp")
+
+        expected = [['Phenotype ID: 29ae0615-0d77-4814-97c7-c9e91f6bfd7b'],
+                    ['Phenotype URL: http://genenetwork.org/show_trait?trait_id=29ae0615-0d77-4814-97c7-c9e91f6bfd7b&dataset=Temp'], [
+                        'Group: name'], ['Phenotype: Description'],
+                    ['Authors: N/A'], ['Title: research1'],
+                    ['Journal: N/A'], ['Dataset Link: http://gn1.genenetwork.org/webqtl/main.py?FormID=sharinginfo&InfoPageName=Temp'], []]
+
+        self.assertEqual(results, expected)
+
+    @mock.patch("wqflask.show_trait.export_trait_data.dict_to_sorted_list")
+    @mock.patch("wqflask.show_trait.export_trait_data.get_export_metadata")
+    def test_export_sample_table(self, exp_metadata, dict_list):
+        """test for  exporting sample table"""
+        targs_obj = {
+            "export_data": """{
+                "primary_samples": [
+                    {
+                        "other": "germanotta",
+                        "name": "Sauroniops",
+                        "se":{
+                        "name":"S2"
+                        },
+                        "num_cases":{
+                        "k1":"value"
+
+                        }
+                    }
+                ],
+                "other_samples": [
+                    {
+                        "se": 1,
+                        "num_cases": 4,
+                        "value": 6,
+                        "name": 3
+                    }
+                ]
+            }""",
+            "trait_display_name": "Hair_color",
+            "trait_id": "23177fdc-312e-4084-ad0c-f3eae785fff5",
+            "dataset": {
+            }
+        }
+        exp_metadata.return_value = [
+            ["Phenotype ID:0a2be192-57f5-400b-bbbd-0cf50135995f"], ['Group:gp1'],
+            ["Phenotype:p1"], [
+                "Authors:N/A"],
+            ["Title:research1"],
+            ["Journal:N/A"],
+            ["Dataset Link: http://gn1.genenetwork.org/webqtl/main.py?FormID=sharinginfo&InfoPageName=name1"], []]
+        expected = ('Hair_color',
+                    [['Phenotype ID:0a2be192-57f5-400b-bbbd-0cf50135995f'],
+                     ['Group:gp1'],
+                     ['Phenotype:p1'],
+                     ['Authors:N/A'],
+                     ['Title:research1'],
+                     ['Journal:N/A'],
+                     ['Dataset Link: '
+                      'http://gn1.genenetwork.org/webqtl/main.py?FormID=sharinginfo&InfoPageName=name1'],
+                     [],
+                     ['Name', 'Value', 'SE', 'N'],
+                     ['Sauroniops', 'germanotta'],
+                     [3, 6, 1, 4]])
+
+        dict_list.side_effect = [['Sauroniops', 'germanotta'], [3, 6, 1, 4]]
+
+        self.assertEqual(export_sample_table(targs_obj), expected)
+        exp_metadata.assert_called_with(
+            "23177fdc-312e-4084-ad0c-f3eae785fff5", {})
+        self.assertEqual(dict_list.call_count, 2)
+
+    def test_dict_to_sortedlist(self):
+        """test for conversion of dict to sorted list"""
+        sample1 = {
+            "other": "exp1",
+            "name": "exp2"
+        }
+        sample2 = {
+            "se": 1,
+            "num_cases": 4,
+            "value": 6,
+            "name": 3
+
+        }
+        rever = {
+            "name": 3,
+            "value": 6,
+            "num_cases": 4,
+            "se": 1
+        }
+        oneItem = {
+            "item1": "one"
+        }
+
+        self.assertEqual(["exp2", "exp1"], dict_to_sorted_list(sample1))
+        self.assertEqual([3, 6, 1, 4], dict_to_sorted_list(sample2))
+        self.assertEqual([3, 6, 1, 4], dict_to_sorted_list(rever))
+        self.assertEqual(["one"], dict_to_sorted_list(oneItem))
+        """test that the func returns the values not the keys"""
+        self.assertFalse(["other", "name"] == dict_to_sorted_list(sample1))
+
+    def test_cmp_samples(self):
+        """test for comparing samples function"""
+        sampleA = [
+            [
+                ("value", "other"),
+                ("name", "test_name")
+            ]
+        ]
+        sampleB = [
+            [
+                ("value", "other"),
+                ("unknown", "test_name")
+            ]
+        ]
+        sampleC = [
+            [("other", "value"),
+             ("name", "value")
+             ],
+            [
+                ("name", "value"),
+                ("value", "name")
+            ],
+            [
+                ("other", "value"),
+                ("name", "value"
+                 )],
+            [
+                ("name", "name1"),
+                ("se", "valuex")
+            ],
+            [(
+                "value", "name1"),
+                ("se", "valuex")
+             ],
+            [(
+                "other", "name1"),
+                ("se", "valuex"
+                 )
+             ],
+            [(
+                "name", "name_val"),
+                ("num_cases", "num_val")
+             ],
+            [(
+                "other_a", "val_a"),
+                ("other_b", "val"
+                 )
+             ]
+        ]
+        results = [cmp_samples(val[0], val[1]) for val in sampleA]
+        resultB = [cmp_samples(val[0], val[1]) for val in sampleB]
+        resultC = [cmp_samples(val[0], val[1]) for val in sampleC]
+
+        self.assertEqual(1, *results)
+        self.assertEqual(-1, *resultB)
+        self.assertEqual([1, -1, 1, -1, -1, 1, -1, -1], resultC)
diff --git a/wqflask/tests/unit/wqflask/snp_browser/__init__.py b/wqflask/tests/unit/wqflask/snp_browser/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/wqflask/tests/unit/wqflask/snp_browser/__init__.py
diff --git a/wqflask/tests/unit/wqflask/snp_browser/test_snp_browser.py b/wqflask/tests/unit/wqflask/snp_browser/test_snp_browser.py
new file mode 100644
index 00000000..89442c47
--- /dev/null
+++ b/wqflask/tests/unit/wqflask/snp_browser/test_snp_browser.py
@@ -0,0 +1,105 @@
+import unittest
+from unittest import mock
+from wqflask import app
+from wqflask.snp_browser.snp_browser import get_gene_id
+from wqflask.snp_browser.snp_browser import get_gene_id_name_dict
+from wqflask.snp_browser.snp_browser import check_if_in_gene
+from wqflask.snp_browser.snp_browser import get_browser_sample_lists
+from wqflask.snp_browser.snp_browser import get_header_list
+
+
+class TestSnpBrowser(unittest.TestCase):
+    def setUp(self):
+        self.app_context = app.app_context()
+        self.app_context.push()
+
+    def tearDown(self):
+        self.app_context.pop()
+
+    def test_get_header_list(self):
+        empty_columns = {"snp_source": "false", "conservation_score": "true", "gene_name": "false",
+                         "transcript": "false", "exon": "false", "domain_2": "true", "function": "false", "function_details": "true"}
+        strains = {"mouse": ["S1", "S2", "S3", "S4", "S5"], "rat": []}
+        expected_results = ([['Index', 'SNP ID', 'Chr', 'Mb', 'Alleles', 'ConScore',
+                              'Domain 1', 'Domain 2', 'Details'],
+                             ['S1', 'S2', 'S3', 'S4', 'S5']], 5,
+                            ['index', 'snp_name', 'chr', 'mb_formatted', 'alleles',
+                             'conservation_score', 'domain_1', 'domain_2',
+                             'function_details', 'S1', 'S2', 'S3', 'S4', 'S5'])
+
+        results_with_snp = get_header_list(
+            variant_type="SNP", strains=strains, species="Mouse", empty_columns=empty_columns)
+        results_with_indel = get_header_list(
+            variant_type="InDel", strains=strains, species="rat", empty_columns=[])
+        expected_results_with_indel = (
+            ['Index', 'ID', 'Type', 'InDel Chr', 'Mb Start',
+             'Mb End', 'Strand', 'Size', 'Sequence', 'Source'], 0,
+            ['index', 'indel_name', 'indel_type', 'indel_chr', 'indel_mb_s',
+             'indel_mb_e', 'indel_strand', 'indel_size', 'indel_sequence', 'source_name'])
+
+        self.assertEqual(expected_results, results_with_snp)
+        self.assertEqual(expected_results_with_indel, results_with_indel)
+
+    @mock.patch("wqflask.snp_browser.snp_browser.g")
+    def test_get_gene_id(self, mock_db):
+        mock_db.db.execute.return_value.fetchone.return_value = "517d729f-aa13-4413-a885-40a3f7ff768a"
+        db_query_value = """
+                SELECT
+                        geneId
+                FROM
+                        GeneList
+                WHERE
+                        SpeciesId = c9c0f59e-1259-4cba-91e6-831ef1a99c83 AND geneSymbol = 'INSR'
+            """
+        results = get_gene_id(
+            species_id="c9c0f59e-1259-4cba-91e6-831ef1a99c83", gene_name="INSR")
+        mock_db.db.execute.assert_called_once_with(db_query_value)
+        self.assertEqual(results, "517d729f-aa13-4413-a885-40a3f7ff768a")
+
+    @mock.patch("wqflask.snp_browser.snp_browser.g")
+    def test_gene_id_name_dict(self, mock_db):
+        no_gene_names = []
+        self.assertEqual("", get_gene_id_name_dict(
+            species_id="fregb343bui43g4", gene_name_list=no_gene_names))
+        gene_name_list = ["GH1", "GH2", "GH3"]
+        mock_db.db.execute.return_value.fetchall.side_effect = [[], [("fsdf43-fseferger-f22", "GH1"), ("1sdf43-fsewferger-f22", "GH2"),
+                                                                     ("fwdj43-fstferger-f22", "GH3")]]
+        no_results = get_gene_id_name_dict(
+            species_id="ret3-32rf32", gene_name_list=gene_name_list)
+        results_found = get_gene_id_name_dict(
+            species_id="ret3-32rf32", gene_name_list=gene_name_list)
+        expected_found = {'GH1': 'fsdf43-fseferger-f22',
+                          'GH2': '1sdf43-fsewferger-f22', 'GH3': 'fwdj43-fstferger-f22'}
+        db_query_value = """
+                SELECT
+                        geneId, geneSymbol
+                FROM
+                        GeneList
+                WHERE
+                        SpeciesId = ret3-32rf32 AND geneSymbol in ('GH1','GH2','GH3')
+            """
+        mock_db.db.execute.assert_called_with(db_query_value)
+        self.assertEqual(results_found, expected_found)
+        self.assertEqual(no_results, {})
+
+    @mock.patch("wqflask.snp_browser.snp_browser.g")
+    def test_check_if_in_gene(self, mock_db):
+        mock_db.db.execute.return_value.fetchone.side_effect = [
+            ("fsdf-232sdf-sdf", "GHA"), ""]
+        results_found = check_if_in_gene(
+            species_id="517d729f-aa13-4413-a885-40a3f7ff768a", chr="CH1", mb=12.09)
+        db_query_value = """SELECT geneId, geneSymbol
+                   FROM GeneList
+                   WHERE SpeciesId = 517d729f-aa13-4413-a885-40a3f7ff768a AND chromosome = 'CH1' AND
+                        (txStart < 12.09 AND txEnd > 12.09); """
+        gene_not_found = check_if_in_gene(
+            species_id="517d729f-aa13-4413-a885-40a3f7ff768a", chr="CH1", mb=12.09)
+        mock_db.db.execute.assert_called_with(db_query_value)
+        self.assertEqual(gene_not_found, "")
+
+    @mock.patch("wqflask.snp_browser.snp_browser.g")
+    def test_get_browser_sample_lists(self, mock_db):
+        mock_db.db.execute.return_value.fetchall.return_value = []
+
+        results = get_browser_sample_lists(species_id="12")
+        self.assertEqual(results, {'mouse': [], 'rat': []})
diff --git a/wqflask/tests/unit/wqflask/test_collect.py b/wqflask/tests/unit/wqflask/test_collect.py
new file mode 100644
index 00000000..2a914fb2
--- /dev/null
+++ b/wqflask/tests/unit/wqflask/test_collect.py
@@ -0,0 +1,75 @@
+"""Test cases for some methods in collect.py"""
+
+import unittest
+from unittest import mock
+
+from flask import Flask
+from wqflask.collect import process_traits
+
+app = Flask(__name__)
+
+
+class MockSession:
+    """Helper class for mocking wqflask.collect.g.user_session.logged_in"""
+
+    def __init__(self, is_logged_in=False):
+        self.is_logged_in = is_logged_in
+
+    @property
+    def logged_in(self):
+        return self.is_logged_in
+
+
+class MockFlaskG:
+    """Helper class for mocking wqflask.collect.g.user_session"""
+
+    def __init__(self, is_logged_in=False):
+        self.is_logged_in = is_logged_in
+
+    @property
+    def user_session(self):
+        if self.is_logged_in:
+            return MockSession(is_logged_in=True)
+        return MockSession()
+
+
+class TestCollect(unittest.TestCase):
+
+    def setUp(self):
+        self.app_context = app.app_context()
+        self.app_context.push()
+
+    def tearDown(self):
+        self.app_context.pop()
+
+    @mock.patch("wqflask.collect.g", MockFlaskG())
+    def test_process_traits_with_bytestring(self):
+        """
+        Test that the correct traits are returned when the user is logged
+        out and bytes are used.
+        """
+        self.assertEqual(process_traits(
+            b'1452452_at:HC_M2_0606_P:163d04f7db7c9e110de6,'
+            b'1452447_at:HC_M2_0606_P:eeece8fceb67072debea,'
+            b'1451401_a_at:HC_M2_0606_P:a043d23b3b3906d8318e,'
+            b'1429252_at:HC_M2_0606_P:6fa378b349bc9180e8f5'),
+            set(['1429252_at:HC_M2_0606_P',
+                 '1451401_a_at:HC_M2_0606_P',
+                 '1452447_at:HC_M2_0606_P',
+                 '1452452_at:HC_M2_0606_P']))
+
+    @mock.patch("wqflask.collect.g", MockFlaskG())
+    def test_process_traits_with_normal_string(self):
+        """
+        Test that the correct traits are returned when the user is logged
+        out and a normal string is used.
+        """
+        self.assertEqual(process_traits(
+            '1452452_at:HC_M2_0606_P:163d04f7db7c9e110de6,'
+            '1452447_at:HC_M2_0606_P:eeece8fceb67072debea,'
+            '1451401_a_at:HC_M2_0606_P:a043d23b3b3906d8318e,'
+            '1429252_at:HC_M2_0606_P:6fa378b349bc9180e8f5'),
+            set(['1429252_at:HC_M2_0606_P',
+                 '1451401_a_at:HC_M2_0606_P',
+                 '1452447_at:HC_M2_0606_P',
+                 '1452452_at:HC_M2_0606_P']))
diff --git a/wqflask/tests/unit/wqflask/test_pbkdf2.py b/wqflask/tests/unit/wqflask/test_pbkdf2.py
new file mode 100644
index 00000000..7ad6c83e
--- /dev/null
+++ b/wqflask/tests/unit/wqflask/test_pbkdf2.py
@@ -0,0 +1,61 @@
+"""Test cases pbkdf2"""
+
+import unittest
+from wqflask.pbkdf2 import pbkdf2_hex
+
+
+class TestPbkdf2(unittest.TestCase):
+    def test_pbkdf2_hex(self):
+        """
+        Test pbkdf2_hex function
+        """
+
+        for password, salt, iterations, keylen, expected_value in [
+                ('password', b'salt', 1, 20,
+                 '0c60c80f961f0e71f3a9b524af6012062fe037a6'),
+                ('password', b'salt', 2, 20,
+                 'ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957'),
+                ('password', b'salt', 4096, 20,
+                 '4b007901b765489abead49d926f721d065a429c1'),
+                ('passwordPASSWORDpassword',
+                 b'saltSALTsaltSALTsaltSALTsaltSALTsalt',
+                 4096, 25,
+                 '3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038'),
+                ('pass\x00word', b'sa\x00lt', 4096, 16,
+                 '56fa6aa75548099dcc37d7f03425e0c3'),
+                ('password', b'ATHENA.MIT.EDUraeburn', 1, 16,
+                 'cdedb5281bb2f801565a1122b2563515'),
+                ('password', b'ATHENA.MIT.EDUraeburn', 1, 32,
+                 ('cdedb5281bb2f80'
+                  '1565a1122b256351'
+                  '50ad1f7a04bb9f3a33'
+                  '3ecc0e2e1f70837')),
+                ('password', b'ATHENA.MIT.EDUraeburn', 2, 16,
+                 '01dbee7f4a9e243e988b62c73cda935d'),
+                ('password', b'ATHENA.MIT.EDUraeburn', 2, 32,
+                 ('01dbee7f4a9e243e9'
+                  '88b62c73cda935da05'
+                  '378b93244ec8f48a99'
+                  'e61ad799d86')),
+                ('password', b'ATHENA.MIT.EDUraeburn', 1200, 32,
+                 ('5c08eb61fdf71e'
+                  '4e4ec3cf6ba1f55'
+                  '12ba7e52ddbc5e51'
+                  '42f708a31e2e62b1e13')),
+                ('X' * 64, b'pass phrase equals block size', 1200, 32,
+                 ('139c30c0966bc32ba'
+                  '55fdbf212530ac9c5'
+                  'ec59f1a452f5cc9ad'
+                  '940fea0598ed1')),
+                ('X' * 65, b'pass phrase exceeds block size', 1200, 32,
+                 ('9ccad6d468770cd'
+                  '51b10e6a68721be6'
+                  '11a8b4d282601db3'
+                  'b36be9246915ec82a'))
+        ]:
+            self.assertEqual(
+                pbkdf2_hex(data=password,
+                           salt=salt,
+                           iterations=iterations,
+                           keylen=keylen),
+                expected_value)
diff --git a/wqflask/tests/unit/wqflask/test_resource_manager.py b/wqflask/tests/unit/wqflask/test_resource_manager.py
new file mode 100644
index 00000000..01fb2021
--- /dev/null
+++ b/wqflask/tests/unit/wqflask/test_resource_manager.py
@@ -0,0 +1,94 @@
+"""Test cases for wqflask/resource_manager.py"""
+import json
+import unittest
+
+from unittest import mock
+from wqflask.resource_manager import get_user_membership
+from wqflask.resource_manager import get_user_access_roles
+from wqflask.resource_manager import DataRole
+from wqflask.resource_manager import AdminRole
+
+
+class TestGetUserMembership(unittest.TestCase):
+    """Test cases for `get_user_membership`"""
+
+    def setUp(self):
+        conn = mock.MagicMock()
+        conn.hgetall.return_value = {
+            '7fa95d07-0e2d-4bc5-b47c-448fdc1260b2': (
+                '{"name": "editors", '
+                '"admins": ["8ad942fe-490d-453e-bd37-56f252e41604", "rand"], '
+                '"members": ["8ad942fe-490d-453e-bd37-56f252e41603", '
+                '"rand"], '
+                '"changed_timestamp": "Oct 06 2021 06:39PM", '
+                '"created_timestamp": "Oct 06 2021 06:39PM"}')}
+        self.conn = conn
+
+    def test_user_is_group_member_only(self):
+        """Test that a user is only a group member"""
+        self.assertEqual(
+            get_user_membership(
+                conn=self.conn,
+                user_id="8ad942fe-490d-453e-bd37-56f252e41603",
+                group_id="7fa95d07-0e2d-4bc5-b47c-448fdc1260b2"),
+            {"member": True,
+             "admin": False})
+
+    def test_user_is_group_admin_only(self):
+        """Test that a user is a group admin only"""
+        self.assertEqual(
+            get_user_membership(
+                conn=self.conn,
+                user_id="8ad942fe-490d-453e-bd37-56f252e41604",
+                group_id="7fa95d07-0e2d-4bc5-b47c-448fdc1260b2"),
+            {"member": False,
+             "admin": True})
+
+    def test_user_is_both_group_member_and_admin(self):
+        """Test that a user is both an admin and member of a group"""
+        self.assertEqual(
+            get_user_membership(
+                conn=self.conn,
+                user_id="rand",
+                group_id="7fa95d07-0e2d-4bc5-b47c-448fdc1260b2"),
+            {"member": True,
+             "admin": True})
+
+
+class TestCheckUserAccessRole(unittest.TestCase):
+    """Test cases for `get_user_access_roles`"""
+
+    @mock.patch("wqflask.resource_manager.requests.get")
+    def test_edit_access(self, requests_mock):
+        """Test that the right access roles are set"""
+        response = mock.PropertyMock(return_value=json.dumps(
+            {
+                'data': ['no-access', 'view', 'edit', ],
+                'metadata': ['no-access', 'view', 'edit', ],
+                'admin': ['not-admin', 'edit-access', ],
+            }
+        ))
+        type(requests_mock.return_value).content = response
+        self.assertEqual(get_user_access_roles(
+            resource_id="0196d92e1665091f202f",
+            user_id="8ad942fe-490d-453e-bd37"),
+            {"data": DataRole.EDIT,
+             "metadata": DataRole.EDIT,
+             "admin": AdminRole.EDIT_ACCESS})
+
+    @mock.patch("wqflask.resource_manager.requests.get")
+    def test_no_access(self, requests_mock):
+        response = mock.PropertyMock(return_value=json.dumps(
+            {
+                'data': ['no-access', ],
+                'metadata': ['no-access', ],
+                'admin': ['not-admin', ],
+            }
+        ))
+        type(requests_mock.return_value).content = response
+        self.assertEqual(get_user_access_roles(
+            resource_id="0196d92e1665091f202f",
+            user_id=""),
+            {"data": DataRole.NO_ACCESS,
+             "metadata": DataRole.NO_ACCESS,
+             "admin": AdminRole.NOT_ADMIN})
diff --git a/wqflask/tests/unit/wqflask/test_server_side.py b/wqflask/tests/unit/wqflask/test_server_side.py
new file mode 100644
index 00000000..be7ca2df
--- /dev/null
+++ b/wqflask/tests/unit/wqflask/test_server_side.py
@@ -0,0 +1,34 @@
+import unittest
+
+from wqflask.server_side import ServerSideTable
+
+
+class TestServerSideTableTests(unittest.TestCase):
+    """
+    Test the ServerSideTable class
+
+    test table:
+        first, second, third
+        'd', 4, 'zz'
+        'b', 2, 'aa'
+        'c', 1, 'ss'
+    """
+
+    def test_get_page(self):
+        rows_count = 3
+        table_rows = [
+            {'first': 'd', 'second': 4, 'third': 'zz'},
+            {'first': 'b', 'second': 2, 'third': 'aa'},
+            {'first': 'c', 'second': 1, 'third': 'ss'},
+        ]
+        headers = ['first', 'second', 'third']
+        request_args = {'sEcho': '1', 'iSortCol_0': '1', 'iSortingCols': '1',
+                        'sSortDir_0': 'asc', 'iDisplayStart': '0', 'iDisplayLength': '3'}
+
+        test_page = ServerSideTable(
+            rows_count, table_rows, headers, request_args).get_page()
+        self.assertEqual(test_page['sEcho'], '1')
+        self.assertEqual(test_page['iTotalRecords'], 'nan')
+        self.assertEqual(test_page['iTotalDisplayRecords'], '3')
+        self.assertEqual(test_page['data'], [{'first': 'b', 'second': 2, 'third': 'aa'}, {
+                         'first': 'c', 'second': 1, 'third': 'ss'}, {'first': 'd', 'second': 4, 'third': 'zz'}])
diff --git a/wqflask/tests/unit/wqflask/test_user_login.py b/wqflask/tests/unit/wqflask/test_user_login.py
new file mode 100644
index 00000000..61cd9ab9
--- /dev/null
+++ b/wqflask/tests/unit/wqflask/test_user_login.py
@@ -0,0 +1,21 @@
+"""Test cases for some methods in login.py"""
+
+import unittest
+from wqflask.user_login import encode_password
+
+
+class TestUserLogin(unittest.TestCase):
+    def test_encode_password(self):
+        """
+        Test encode password
+        """
+        pass_gen_fields = {
+            "salt": "salt",
+            "hashfunc": "sha1",
+            "iterations": 4096,
+            "keylength": 20,
+        }
+        self.assertEqual(
+            encode_password(pass_gen_fields,
+                            "password").get("password"),
+            '4b007901b765489abead49d926f721d065a429c1')
diff --git a/wqflask/tests/unit/wqflask/test_user_session.py b/wqflask/tests/unit/wqflask/test_user_session.py
new file mode 100644
index 00000000..ebb0334a
--- /dev/null
+++ b/wqflask/tests/unit/wqflask/test_user_session.py
@@ -0,0 +1,15 @@
+"""Test cases for some methods in user_session.py"""
+
+import unittest
+from wqflask.user_session import verify_cookie
+
+
+class TestUserSession(unittest.TestCase):
+    def test_verify_cookie(self):
+        """
+        Test cookie verification
+        """
+        self.assertEqual(
+            "3f4c1dbf-5b56-4260-87d6-f35445bda37e",
+            verify_cookie(("3f4c1dbf-5b56-4260-87d6-"
+                           "f35445bda37e:af4fcf5eace9e7c864ce")))
diff --git a/wqflask/tests/unit/wqflask/wgcna/__init__.py b/wqflask/tests/unit/wqflask/wgcna/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/wqflask/tests/unit/wqflask/wgcna/__init__.py
diff --git a/wqflask/tests/unit/wqflask/wgcna/test_wgcna.py b/wqflask/tests/unit/wqflask/wgcna/test_wgcna.py
new file mode 100644
index 00000000..8e947e2f
--- /dev/null
+++ b/wqflask/tests/unit/wqflask/wgcna/test_wgcna.py
@@ -0,0 +1,50 @@
+
+"""module contains for processing gn3 wgcna data"""
+from unittest import TestCase
+
+from wqflask.wgcna.gn3_wgcna import process_wgcna_data
+
+
+class DataProcessingTests(TestCase):
+    """class contains data processing tests"""
+
+    def test_data_processing(self):
+        """test for parsing data for datatable"""
+        output = {
+            "input": {
+                "sample_names": ["BXD1", "BXD2", "BXD3", "BXD4", "BXD5", "BXD6"],
+
+            },
+            "output": {
+                "ModEigens": {
+                    "MEturquoise": [
+                        0.0646677768085351,
+                        0.137200224277058,
+                        0.63451113720732,
+                        -0.544002665501479,
+                        -0.489487590361863,
+                        0.197111117570427
+                    ],
+                    "MEgrey": [
+                        0.213,
+                        0.214,
+                        0.3141,
+                        -0.545,
+                        -0.423,
+                        0.156,
+                    ]
+                }}}
+
+        row_data = [['BXD1', 0.065, 0.213],
+                    ['BXD2', 0.137, 0.214],
+                    ['BXD3', 0.635, 0.314],
+                    ['BXD4', -0.544, -0.545],
+                    ['BXD5', -0.489, -0.423],
+                    ['BXD6', 0.197, 0.156]]
+
+        expected_results = {
+            "col_names": ["sample_names", "MEturquoise", "MEgrey"],
+            "mod_dataset": row_data
+        }
+
+        self.assertEqual(process_wgcna_data(output), expected_results)