diff options
author | Frederick Muriuki Muriithi | 2022-02-14 06:56:32 +0300 |
---|---|---|
committer | Frederick Muriuki Muriithi | 2022-02-17 06:37:30 +0300 |
commit | 74044f3c7985308b4996da3a52f91c5c20a19194 (patch) | |
tree | d86714b859b31cbbd1755522f8abd8eed16e321b | |
parent | 67f517aa0f44f55dc691ffd791bf22ef7af0b02c (diff) | |
download | genenetwork3-74044f3c7985308b4996da3a52f91c5c20a19194.tar.gz |
Use pytest's "mark" feature to categorise tests
Use pytest's `mark` feature to explicitly categorise the tests and run them
per category
29 files changed, 198 insertions, 13 deletions
diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..58eba11 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,6 @@ +[pytest] +addopts = --strict-markers +markers = + unit_test + integration_test + performance_test
\ No newline at end of file diff --git a/setup_commands/run_tests.py b/setup_commands/run_tests.py index 9a2c9ad..1bb5dab 100644 --- a/setup_commands/run_tests.py +++ b/setup_commands/run_tests.py @@ -7,21 +7,18 @@ class RunTests(Command): A custom command to run tests. """ description = "Run the tests" - commands = { - "all": "pytest", - "unit": "pytest tests/unit", - "integration": "pytest tests/integration", - "performance": "pytest tests/performance", - } + test_types = ( + "all", "unit", "integration", "performance") user_options = [ ("type=", None, f"""Specify the type of tests to run. - Valid types are {tuple(commands.keys())}. + Valid types are {tuple(test_types)}. Default is `all`.""")] def __init__(self, dist): """Initialise the command.""" super().__init__(dist) + self.command = "pytest" def initialize_options(self): """Initialise the default values of all the options.""" @@ -29,13 +26,15 @@ class RunTests(Command): def finalize_options(self): """Set final value of all the options once they are processed.""" - if self.type not in RunTests.commands.keys(): + if self.type not in RunTests.test_types: raise Exception(f""" Invalid test type (self.type) requested! Valid types are - {tuple(RunTests.commands.keys())}""") + {tuple(RunTests.test_types)}""") + if self.type != "all": + self.command = f"pytest -m {self.type}_test" def run(self): """Run the chosen tests""" print(f"Running {self.type} tests") - os.system(RunTests.commands[self.type]) + os.system(self.command) diff --git a/tests/integration/test_correlation.py b/tests/integration/test_correlation.py index bdd9bce..cf63c17 100644 --- a/tests/integration/test_correlation.py +++ b/tests/integration/test_correlation.py @@ -1,6 +1,7 @@ """module contains integration tests for correlation""" from unittest import TestCase from unittest import mock +import pytest from gn3.app import create_app @@ -10,6 +11,7 @@ class CorrelationIntegrationTest(TestCase): def setUp(self): self.app = create_app().test_client() + @pytest.mark.integration_test @mock.patch("gn3.api.correlation.compute_all_sample_correlation") def test_sample_r_correlation(self, mock_compute_samples): """Test /api/correlation/sample_r/{method}""" @@ -61,6 +63,7 @@ class CorrelationIntegrationTest(TestCase): self.assertEqual(response.status_code, 200) self.assertEqual(response.get_json(), api_response) + @pytest.mark.integration_test @mock.patch("gn3.api.correlation.compute_all_lit_correlation") @mock.patch("gn3.api.correlation.database_connector") def test_lit_correlation(self, database_connector, mock_compute_corr): @@ -80,6 +83,7 @@ class CorrelationIntegrationTest(TestCase): self.assertEqual(mock_compute_corr.call_count, 1) self.assertEqual(response.status_code, 200) + @pytest.mark.integration_test @mock.patch("gn3.api.correlation.compute_tissue_correlation") def test_tissue_correlation(self, mock_tissue_corr): """Test api/correlation/tissue_corr/{corr_method}""" diff --git a/tests/integration/test_gemma.py b/tests/integration/test_gemma.py index f871173..0515539 100644 --- a/tests/integration/test_gemma.py +++ b/tests/integration/test_gemma.py @@ -7,6 +7,8 @@ from dataclasses import dataclass from typing import Callable from unittest import mock +import pytest + from gn3.app import create_app @@ -30,6 +32,7 @@ class GemmaAPITest(unittest.TestCase): "TMPDIR": "/tmp" }).test_client() + @pytest.mark.integration_test @mock.patch("gn3.api.gemma.run_cmd") def test_get_version(self, mock_run_cmd): """Test that the correct response is returned""" @@ -38,6 +41,7 @@ class GemmaAPITest(unittest.TestCase): self.assertEqual(response.get_json(), {"status": 0, "output": "v1.9"}) self.assertEqual(response.status_code, 200) + @pytest.mark.integration_test @mock.patch("gn3.api.gemma.redis.Redis") def test_check_cmd_status(self, mock_redis): """Test that you can check the status of a given command""" @@ -52,6 +56,7 @@ class GemmaAPITest(unittest.TestCase): name="cmd::2021-02-1217-3224-3224-1234", key="status") self.assertEqual(response.get_json(), {"status": "test"}) + @pytest.mark.integration_test @mock.patch("gn3.api.gemma.queue_cmd") @mock.patch("gn3.computations.gemma.get_hash_of_files") @mock.patch("gn3.api.gemma.jsonfile_to_dict") @@ -94,6 +99,7 @@ class GemmaAPITest(unittest.TestCase): "unique_id": "my-unique-id" }) + @pytest.mark.integration_test @mock.patch("gn3.api.gemma.queue_cmd") @mock.patch("gn3.computations.gemma.get_hash_of_files") @mock.patch("gn3.api.gemma.jsonfile_to_dict") @@ -137,6 +143,7 @@ class GemmaAPITest(unittest.TestCase): "unique_id": "my-unique-id" }) + @pytest.mark.integration_test @mock.patch("gn3.api.gemma.queue_cmd") @mock.patch("gn3.computations.gemma.get_hash_of_files") @mock.patch("gn3.api.gemma.jsonfile_to_dict") @@ -187,6 +194,7 @@ class GemmaAPITest(unittest.TestCase): "output_file": "hash-output.json" }) + @pytest.mark.integration_test @mock.patch("gn3.api.gemma.queue_cmd") @mock.patch("gn3.computations.gemma.get_hash_of_files") @mock.patch("gn3.api.gemma.jsonfile_to_dict") @@ -240,6 +248,7 @@ class GemmaAPITest(unittest.TestCase): "output_file": "hash-output.json" }) + @pytest.mark.integration_test @mock.patch("gn3.api.gemma.queue_cmd") @mock.patch("gn3.computations.gemma.get_hash_of_files") @mock.patch("gn3.api.gemma.jsonfile_to_dict") @@ -292,6 +301,7 @@ class GemmaAPITest(unittest.TestCase): "output_file": "hash-output.json" }) + @pytest.mark.integration_test @mock.patch("gn3.api.gemma.queue_cmd") @mock.patch("gn3.computations.gemma.get_hash_of_files") @mock.patch("gn3.api.gemma.jsonfile_to_dict") @@ -346,6 +356,7 @@ class GemmaAPITest(unittest.TestCase): "output_file": "hash-output.json" }) + @pytest.mark.integration_test @mock.patch("gn3.api.gemma.queue_cmd") @mock.patch("gn3.computations.gemma.get_hash_of_files") @mock.patch("gn3.api.gemma.jsonfile_to_dict") @@ -401,6 +412,7 @@ class GemmaAPITest(unittest.TestCase): "output_file": "hash-output.json" }) + @pytest.mark.integration_test @mock.patch("gn3.api.gemma.queue_cmd") @mock.patch("gn3.computations.gemma.get_hash_of_files") @mock.patch("gn3.api.gemma.jsonfile_to_dict") @@ -465,6 +477,7 @@ class GemmaAPITest(unittest.TestCase): "output_file": "hash-output.json" }) + @pytest.mark.integration_test @mock.patch("gn3.api.gemma.queue_cmd") @mock.patch("gn3.computations.gemma.get_hash_of_files") @mock.patch("gn3.api.gemma.jsonfile_to_dict") @@ -530,6 +543,7 @@ class GemmaAPITest(unittest.TestCase): "output_file": "hash-output.json" }) + @pytest.mark.integration_test @mock.patch("gn3.api.gemma.queue_cmd") @mock.patch("gn3.computations.gemma.get_hash_of_files") @mock.patch("gn3.api.gemma.jsonfile_to_dict") diff --git a/tests/integration/test_general.py b/tests/integration/test_general.py index 8fc2b43..9d87449 100644 --- a/tests/integration/test_general.py +++ b/tests/integration/test_general.py @@ -1,8 +1,10 @@ """Integration tests for some 'general' API endpoints""" import os import unittest - from unittest import mock + +import pytest + from gn3.app import create_app @@ -11,6 +13,7 @@ class GeneralAPITest(unittest.TestCase): def setUp(self): self.app = create_app().test_client() + @pytest.mark.integration_test def test_metadata_endpoint_exists(self): """Test that /metadata/upload exists""" response = self.app.post("/api/metadata/upload/d41d86-e4ceEo") @@ -19,6 +22,7 @@ class GeneralAPITest(unittest.TestCase): {"status": 128, "error": "Please provide a file!"}) + @pytest.mark.integration_test @mock.patch("gn3.api.general.extract_uploaded_file") def test_metadata_file_upload(self, mock_extract_upload): """Test correct upload of file""" @@ -37,6 +41,7 @@ class GeneralAPITest(unittest.TestCase): {"status": 0, "token": "d41d86-e4ceEo"}) + @pytest.mark.integration_test def test_metadata_file_wrong_upload(self): """Test that incorrect upload return correct status code""" response = self.app.post("/api/metadata/upload/d41d86-e4ceEo", @@ -47,6 +52,7 @@ class GeneralAPITest(unittest.TestCase): {"status": 128, "error": "gzip failed to unpack file"}) + @pytest.mark.integration_test @mock.patch("gn3.api.general.run_cmd") def test_run_r_qtl(self, mock_run_cmd): """Test correct upload of file""" diff --git a/tests/integration/test_wgcna.py b/tests/integration/test_wgcna.py index 078449d..5880b40 100644 --- a/tests/integration/test_wgcna.py +++ b/tests/integration/test_wgcna.py @@ -3,6 +3,8 @@ from unittest import TestCase from unittest import mock +import pytest + from gn3.app import create_app @@ -12,6 +14,7 @@ class WgcnaIntegrationTest(TestCase): def setUp(self): self.app = create_app().test_client() + @pytest.mark.integration_test @mock.patch("gn3.api.wgcna.call_wgcna_script") def test_wgcna_endpoint(self, mock_wgcna_script): """test /api/wgcna/run_wgcna endpoint""" diff --git a/tests/unit/computations/test_correlation.py b/tests/unit/computations/test_correlation.py index 7523d99..69d4c52 100644 --- a/tests/unit/computations/test_correlation.py +++ b/tests/unit/computations/test_correlation.py @@ -2,6 +2,7 @@ from unittest import TestCase from unittest import mock +import pytest from collections import namedtuple import math from numpy.testing import assert_almost_equal @@ -91,6 +92,7 @@ class DataBase(QueryableMixin): class TestCorrelation(TestCase): """Class for testing correlation functions""" + @pytest.mark.unit_test def test_normalize_values(self): """Function to test normalizing values """ @@ -106,6 +108,7 @@ class TestCorrelation(TestCase): results = normalize_values(a_values, b_values) self.assertEqual(list(zip(*list(results))), expected_result) + @pytest.mark.unit_test @mock.patch("gn3.computations.correlations.compute_corr_coeff_p_value") @mock.patch("gn3.computations.correlations.normalize_values") def test_compute_sample_r_correlation(self, norm_vals, compute_corr): @@ -130,6 +133,7 @@ class TestCorrelation(TestCase): self.assertEqual(bicor_results, ("1412_at", 0.8, 0.21, 7)) + @pytest.mark.unit_test def test_filter_shared_sample_keys(self): """Function to tests shared key between two dicts""" @@ -157,6 +161,7 @@ class TestCorrelation(TestCase): self.assertEqual(list(zip(*list(results))), [filtered_this_samplelist, filtered_target_samplelist]) + @pytest.mark.unit_test @mock.patch("gn3.computations.correlations.compute_sample_r_correlation") @mock.patch("gn3.computations.correlations.filter_shared_sample_keys") def test_compute_all_sample(self, filter_shared_samples, sample_r_corr): @@ -199,6 +204,7 @@ class TestCorrelation(TestCase): corr_method="pearson", trait_vals=('1.23', '6.565', '6.456'), target_samples_vals=('6.266', '6.565', '6.456')) + @pytest.mark.unit_test @mock.patch("gn3.computations.correlations.compute_corr_coeff_p_value") def test_tissue_correlation_for_trait(self, mock_compute_corr_coeff): """Test given a primary tissue values for a trait and and a list of\ @@ -217,6 +223,7 @@ class TestCorrelation(TestCase): self.assertEqual(tissue_results, expected_tissue_results) + @pytest.mark.unit_test @mock.patch("gn3.computations.correlations.fetch_lit_correlation_data") @mock.patch("gn3.computations.correlations.map_to_mouse_gene_id") def test_lit_correlation_for_trait(self, mock_mouse_gene_id, fetch_lit_data): @@ -244,6 +251,7 @@ class TestCorrelation(TestCase): self.assertEqual(lit_results, expected_results) + @pytest.mark.unit_test def test_fetch_lit_correlation_data(self): """Test for fetching lit correlation data from\ the database where the input and mouse geneid are none @@ -257,6 +265,7 @@ class TestCorrelation(TestCase): self.assertEqual(results, ("1", 0)) + @pytest.mark.unit_test def test_fetch_lit_correlation_data_db_query(self): """Test for fetching lit corr coefficent givent the input\ input trait mouse gene id and mouse gene id @@ -274,6 +283,7 @@ class TestCorrelation(TestCase): self.assertEqual(expected_results, lit_results) + @pytest.mark.unit_test def test_query_lit_correlation_for_db_empty(self): """Test that corr coeffient returned is 0 given the\ db value if corr coefficient is empty @@ -289,6 +299,7 @@ class TestCorrelation(TestCase): self.assertEqual(lit_results, ("16", 0)) + @pytest.mark.unit_test def test_query_formatter(self): """Test for formatting a query given the query string and also the\ values @@ -316,6 +327,7 @@ class TestCorrelation(TestCase): self.assertEqual(formatted_query, expected_formatted_query) + @pytest.mark.unit_test def test_query_formatter_no_query_values(self): """Test for formatting a query where there are no\ string placeholder @@ -325,6 +337,7 @@ class TestCorrelation(TestCase): self.assertEqual(formatted_query, query) + @pytest.mark.unit_test def test_map_to_mouse_gene_id(self): """Test for converting a gene id to mouse geneid\ given a species which is not mouse @@ -348,6 +361,7 @@ class TestCorrelation(TestCase): self.assertEqual(results, expected_results) + @pytest.mark.unit_test @mock.patch("gn3.computations.correlations.lit_correlation_for_trait") def test_compute_all_lit_correlation(self, mock_lit_corr): """Test for compute all lit correlation which acts\ @@ -368,6 +382,7 @@ class TestCorrelation(TestCase): self.assertEqual(lit_correlation_results, expected_mocked_lit_results) + @pytest.mark.unit_test @mock.patch("gn3.computations.correlations.tissue_correlation_for_trait") @mock.patch("gn3.computations.correlations.process_trait_symbol_dict") def test_compute_all_tissue_correlation(self, process_trait_symbol, mock_tissue_corr): @@ -411,6 +426,7 @@ class TestCorrelation(TestCase): self.assertEqual(results, expected_results) + @pytest.mark.unit_test def test_map_shared_keys_to_values(self): """test helper function needed to integrate with genenenetwork2\ given a a samplelist containing dataset sampelist keys\ @@ -431,6 +447,7 @@ class TestCorrelation(TestCase): self.assertEqual(results, expected_results) + @pytest.mark.unit_test def test_process_trait_symbol_dict(self): """test for processing trait symbol dict\ and fetch tissue values from tissue value dict\ @@ -449,6 +466,7 @@ class TestCorrelation(TestCase): self.assertEqual(results, [expected_results]) + @pytest.mark.unit_test def test_compute_correlation(self): """Test that the new correlation function works the same as the original from genenetwork1.""" diff --git a/tests/unit/computations/test_dictify_by_samples.py b/tests/unit/computations/test_dictify_by_samples.py index decc095..8a1332f 100644 --- a/tests/unit/computations/test_dictify_by_samples.py +++ b/tests/unit/computations/test_dictify_by_samples.py @@ -63,6 +63,7 @@ values = st.lists(st.floats()) variances = st.lists(st.one_of(st.none(), st.floats())) other = st.lists(st.integers()) +@pytest.mark.unit_test @given(svv=st.tuples( st.lists(non_empty_samples), st.lists(values), diff --git a/tests/unit/computations/test_diff.py b/tests/unit/computations/test_diff.py index e4f5dde..128fb60 100644 --- a/tests/unit/computations/test_diff.py +++ b/tests/unit/computations/test_diff.py @@ -2,6 +2,8 @@ import unittest import os +import pytest + from gn3.computations.diff import generate_diff TESTDIFF = """3,4c3,4 @@ -19,6 +21,7 @@ TESTDIFF = """3,4c3,4 class TestDiff(unittest.TestCase): """Test cases for computations.diff""" + @pytest.mark.unit_test def test_generate_diff(self): """Test that the correct diff is generated""" data = os.path.join(os.path.dirname(__file__).split("unit")[0], diff --git a/tests/unit/computations/test_gemma.py b/tests/unit/computations/test_gemma.py index 73dd5eb..b36a93e 100644 --- a/tests/unit/computations/test_gemma.py +++ b/tests/unit/computations/test_gemma.py @@ -1,7 +1,9 @@ """Test cases for procedures defined in computations.gemma""" import unittest - from unittest import mock + +import pytest + from gn3.computations.gemma import generate_gemma_cmd from gn3.computations.gemma import generate_hash_of_string from gn3.computations.gemma import generate_pheno_txt_file @@ -9,6 +11,7 @@ from gn3.computations.gemma import generate_pheno_txt_file class TestGemma(unittest.TestCase): """Test cases for computations.gemma module""" + @pytest.mark.unit_test def test_generate_pheno_txt_file(self): """Test that the pheno text file is generated correctly""" open_mock = mock.mock_open() @@ -26,11 +29,13 @@ class TestGemma(unittest.TestCase): mock.call("BXD07 438.700\n") ]) + @pytest.mark.unit_test def test_generate_hash_of_string(self): """Test that a string is hashed correctly""" self.assertEqual(generate_hash_of_string("I^iQP&TlSR^z"), "hMVRw8kbEp49rOmoIkhMjA") + @pytest.mark.unit_test @mock.patch("gn3.computations.gemma.get_hash_of_files") def test_compute_k_values_without_loco(self, mock_get_hash): """Test computing k values without loco""" @@ -52,6 +57,7 @@ class TestGemma(unittest.TestCase): "-gk > /tmp/my-token/my-hash-output.json") }) + @pytest.mark.unit_test @mock.patch("gn3.computations.gemma.get_hash_of_files") def test_generate_gemma_cmd_with_loco(self, mock_get_hash): """Test computing k values with loco""" diff --git a/tests/unit/computations/test_parsers.py b/tests/unit/computations/test_parsers.py index b51b0bf..f05f766 100644 --- a/tests/unit/computations/test_parsers.py +++ b/tests/unit/computations/test_parsers.py @@ -2,17 +2,21 @@ import unittest import os +import pytest + from gn3.computations.parsers import parse_genofile class TestParsers(unittest.TestCase): """Test cases for some various parsers""" + @pytest.mark.unit_test def test_parse_genofile_without_existing_file(self): """Assert that an error is raised if the genotype file is absent""" self.assertRaises(FileNotFoundError, parse_genofile, "/non-existent-file") + @pytest.mark.unit_test def test_parse_genofile_with_existing_file(self): """Test that a genotype file is parsed correctly""" samples = ["bxd1", "bxd2"] diff --git a/tests/unit/computations/test_partial_correlations.py b/tests/unit/computations/test_partial_correlations.py index 3690ca4..ee17659 100644 --- a/tests/unit/computations/test_partial_correlations.py +++ b/tests/unit/computations/test_partial_correlations.py @@ -3,6 +3,7 @@ from unittest import TestCase import pandas +import pytest from numpy.testing import assert_allclose from gn3.computations.partial_correlations import ( @@ -98,6 +99,7 @@ dictified_control_samples = ( class TestPartialCorrelations(TestCase): """Class for testing partial correlations computation functions""" + @pytest.mark.unit_test def test_control_samples(self): """Test that the control_samples works as expected.""" self.assertEqual( @@ -112,6 +114,7 @@ class TestPartialCorrelations(TestCase): (None, None, None)), (6, 4, 3))) + @pytest.mark.unit_test def test_dictify_by_samples(self): """ Test that `dictify_by_samples` generates the appropriate dict @@ -142,6 +145,7 @@ class TestPartialCorrelations(TestCase): (6, 4, 3))), dictified_control_samples) + @pytest.mark.unit_test def test_fix_samples(self): """ Test that `fix_samples` returns only the common samples @@ -187,6 +191,7 @@ class TestPartialCorrelations(TestCase): (None, None, None, None, None, None, None, None, None, None, None, None, None))) + @pytest.mark.unit_test def test_find_identical_traits(self): """ Test `gn3.partial_correlations.find_identical_traits`. @@ -219,6 +224,7 @@ class TestPartialCorrelations(TestCase): self.assertEqual( find_identical_traits(primn, primv, contn, contv), expected) + @pytest.mark.unit_test def test_tissue_correlation_error(self): """ Test that `tissue_correlation` raises specific exceptions for particular @@ -253,6 +259,7 @@ class TestPartialCorrelations(TestCase): with self.assertRaises(error, msg=error_msg): tissue_correlation(primary, target, method) + @pytest.mark.unit_test def test_tissue_correlation(self): # pylint: disable=R0201 """ Test that the correct correlation values are computed for the given: @@ -269,6 +276,7 @@ class TestPartialCorrelations(TestCase): assert_allclose( tissue_correlation(primary, target, method), expected) + @pytest.mark.unit_test def test_good_dataset_samples_indexes(self): """ Test that `good_dataset_samples_indexes` returns correct indices. @@ -279,6 +287,7 @@ class TestPartialCorrelations(TestCase): ("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l")), (0, 4, 8, 10)) + @pytest.mark.unit_test def test_build_data_frame(self): """ Check that the function builds the correct data frame. diff --git a/tests/unit/computations/test_qtlreaper.py b/tests/unit/computations/test_qtlreaper.py index 742d106..607f4a6 100644 --- a/tests/unit/computations/test_qtlreaper.py +++ b/tests/unit/computations/test_qtlreaper.py @@ -1,5 +1,6 @@ """Module contains tests for gn3.computations.qtlreaper""" from unittest import TestCase +import pytest from gn3.computations.qtlreaper import ( parse_reaper_main_results, organise_reaper_main_results, @@ -9,6 +10,7 @@ from tests.unit.sample_test_data import organised_trait_1 class TestQTLReaper(TestCase): """Class for testing qtlreaper interface functions.""" + @pytest.mark.unit_test def test_parse_reaper_main_results(self): """Test that the main results file is parsed correctly.""" self.assertEqual( @@ -67,6 +69,7 @@ class TestQTLReaper(TestCase): } ]) + @pytest.mark.unit_test def test_parse_reaper_permutation_results(self): """Test that the permutations results file is parsed correctly.""" self.assertEqual( @@ -77,6 +80,7 @@ class TestQTLReaper(TestCase): 5.63874, 5.71346, 5.71936, 5.74275, 5.76764, 5.79815, 5.81671, 5.82775, 5.89659, 5.92117, 5.93396, 5.93396, 5.94957]) + @pytest.mark.unit_test def test_organise_reaper_main_results(self): """Check that results are organised correctly.""" self.assertEqual( diff --git a/tests/unit/computations/test_rqtl.py b/tests/unit/computations/test_rqtl.py index 955d0ab..51df281 100644 --- a/tests/unit/computations/test_rqtl.py +++ b/tests/unit/computations/test_rqtl.py @@ -2,10 +2,12 @@ import unittest from unittest import mock +import pytest from gn3.computations.rqtl import generate_rqtl_cmd class TestRqtl(unittest.TestCase): """Test cases for computations.rqtl module""" + @pytest.mark.unit_test @mock.patch("gn3.computations.rqtl.generate_hash_of_string") @mock.patch("gn3.computations.rqtl.get_hash_of_files") def test_generate_rqtl_command(self, mock_get_hash_files, mock_generate_hash_string): diff --git a/tests/unit/computations/test_slink.py b/tests/unit/computations/test_slink.py index 995393b..276133a 100644 --- a/tests/unit/computations/test_slink.py +++ b/tests/unit/computations/test_slink.py @@ -1,6 +1,8 @@ """Module contains tests for slink""" from unittest import TestCase +import pytest + from gn3.computations.slink import slink from gn3.computations.slink import nearest from gn3.computations.slink import LengthError @@ -9,6 +11,7 @@ from gn3.computations.slink import MirrorError class TestSlink(TestCase): """Class for testing slink functions""" + @pytest.mark.unit_test def test_nearest_expects_list_of_lists(self): """Test that function only accepts a list of lists.""" # This might be better handled with type-hints and mypy @@ -18,6 +21,7 @@ class TestSlink(TestCase): with self.assertRaises(ValueError, msg="Expected list or tuple"): nearest(item, 1, 1) + @pytest.mark.unit_test def test_nearest_does_not_allow_empty_lists(self): """Test that function does not accept an empty list, or any of the child lists to be empty.""" @@ -29,6 +33,7 @@ class TestSlink(TestCase): with self.assertRaises(ValueError): nearest(lst, 1, 1) + @pytest.mark.unit_test def test_nearest_expects_children_are_same_length_as_parent(self): """Test that children lists are same length as parent list.""" for lst in [[[0, 1]], @@ -40,6 +45,7 @@ class TestSlink(TestCase): with self.assertRaises(LengthError): nearest(lst, 1, 1) + @pytest.mark.unit_test def test_nearest_expects_member_is_zero_distance_from_itself(self): """Test that distance of a member from itself is zero""" for lst in [[[1]], @@ -50,6 +56,7 @@ class TestSlink(TestCase): with self.assertRaises(ValueError): nearest(lst, 1, 1) + @pytest.mark.unit_test def test_nearest_expects_distance_atob_is_equal_to_distance_btoa(self): """Test that the distance from member A to member B is the same as that from member B to member A.""" @@ -60,6 +67,7 @@ class TestSlink(TestCase): with self.assertRaises(MirrorError): nearest(lst, 1, 1) + @pytest.mark.unit_test def test_nearest_expects_zero_or_positive_distances(self): """Test that all distances are either zero, or greater than zero.""" # Based on: @@ -74,6 +82,7 @@ class TestSlink(TestCase): with self.assertRaises(ValueError, msg="Distances should be positive."): nearest(lst, 1, 1) + @pytest.mark.unit_test def test_nearest_returns_shortest_distance_given_coordinates_to_both_group_members(self): """Test that the shortest distance is returned.""" # This test is named wrong - at least I think it is, from the expected results @@ -234,6 +243,7 @@ class TestSlink(TestCase): with self.subTest(lst=lst): self.assertEqual(nearest(lst, i, j), expected) + @pytest.mark.unit_test def test_nearest_gives_shortest_distance_between_list_of_members_and_member(self): """Test that the shortest distance is returned.""" for members_distances, members_list, member_coordinate, expected_distance in [ @@ -260,6 +270,7 @@ class TestSlink(TestCase): members_distances, member_coordinate, members_list), expected_distance) + @pytest.mark.unit_test def test_nearest_returns_shortest_distance_given_two_lists_of_members(self): """Test that the shortest distance is returned.""" for members_distances, members_list, member_list2, expected_distance in [ @@ -289,12 +300,14 @@ class TestSlink(TestCase): members_distances, member_list2, members_list), expected_distance) + @pytest.mark.unit_test def test_slink_wrong_data_returns_empty_list(self): """Test that empty list is returned for wrong data.""" for data in [1, "test", [], 2.945, nearest, [0]]: with self.subTest(data=data): self.assertEqual(slink(data), []) + @pytest.mark.unit_test def test_slink_with_data(self): """Test slink with example data, and expected results for each data sample.""" diff --git a/tests/unit/computations/test_wgcna.py b/tests/unit/computations/test_wgcna.py index 5f23a86..3130374 100644 --- a/tests/unit/computations/test_wgcna.py +++ b/tests/unit/computations/test_wgcna.py @@ -2,6 +2,8 @@ from unittest import TestCase from unittest import mock +import pytest + from gn3.computations.wgcna import dump_wgcna_data from gn3.computations.wgcna import compose_wgcna_cmd from gn3.computations.wgcna import call_wgcna_script @@ -10,6 +12,7 @@ from gn3.computations.wgcna import call_wgcna_script class TestWgcna(TestCase): """test class for wgcna""" + @pytest.mark.unit_test @mock.patch("gn3.computations.wgcna.process_image") @mock.patch("gn3.computations.wgcna.run_cmd") @mock.patch("gn3.computations.wgcna.compose_wgcna_cmd") @@ -95,6 +98,7 @@ class TestWgcna(TestCase): self.assertEqual(results, expected_output) + @pytest.mark.unit_test @mock.patch("gn3.computations.wgcna.run_cmd") @mock.patch("gn3.computations.wgcna.compose_wgcna_cmd") @mock.patch("gn3.computations.wgcna.dump_wgcna_data") @@ -117,6 +121,7 @@ class TestWgcna(TestCase): self.assertEqual(call_wgcna_script( "input_file.R", ""), expected_error) + @pytest.mark.unit_test def test_compose_wgcna_cmd(self): """test for composing wgcna cmd""" wgcna_cmd = compose_wgcna_cmd( @@ -124,6 +129,7 @@ class TestWgcna(TestCase): self.assertEqual( wgcna_cmd, "Rscript ./scripts/wgcna.r /tmp/wgcna.json") + @pytest.mark.unit_test @mock.patch("gn3.computations.wgcna.TMPDIR", "/tmp") @mock.patch("gn3.computations.wgcna.uuid.uuid4") def test_create_json_file(self, file_name_generator): diff --git a/tests/unit/db/test_audit.py b/tests/unit/db/test_audit.py index 7480169..884afc6 100644 --- a/tests/unit/db/test_audit.py +++ b/tests/unit/db/test_audit.py @@ -3,6 +3,8 @@ import json from unittest import TestCase from unittest import mock +import pytest + from gn3.db import insert from gn3.db.metadata_audit import MetadataAudit @@ -10,6 +12,7 @@ from gn3.db.metadata_audit import MetadataAudit class TestMetadatAudit(TestCase): """Test cases for fetching chromosomes""" + @pytest.mark.unit_test def test_insert_into_metadata_audit(self): """Test that data is inserted correctly in the audit table diff --git a/tests/unit/db/test_correlation.py b/tests/unit/db/test_correlation.py index 3f940b2..5afe55f 100644 --- a/tests/unit/db/test_correlation.py +++ b/tests/unit/db/test_correlation.py @@ -4,6 +4,8 @@ Tests for the gn3.db.correlations module from unittest import TestCase +import pytest + from gn3.db.correlations import ( build_query_sgo_lit_corr, build_query_tissue_corr) @@ -12,6 +14,7 @@ class TestCorrelation(TestCase): """Test cases for correlation data fetching functions""" maxDiff = None + @pytest.mark.unit_test def test_build_query_sgo_lit_corr(self): """ Test that the literature correlation query is built correctly. @@ -53,6 +56,7 @@ class TestCorrelation(TestCase): "ORDER BY Probeset.Id"), 2)) + @pytest.mark.unit_test def test_build_query_tissue_corr(self): """ Test that the tissue correlation query is built correctly. diff --git a/tests/unit/db/test_datasets.py b/tests/unit/db/test_datasets.py index 0b8c2fe..5b86db9 100644 --- a/tests/unit/db/test_datasets.py +++ b/tests/unit/db/test_datasets.py @@ -1,6 +1,7 @@ """Tests for gn3/db/datasets.py""" from unittest import mock, TestCase +import pytest from gn3.db.datasets import ( retrieve_dataset_name, retrieve_group_fields, @@ -11,6 +12,7 @@ from gn3.db.datasets import ( class TestDatasetsDBFunctions(TestCase): """Test cases for datasets functions.""" + @pytest.mark.unit_test def test_retrieve_dataset_name(self): """Test that the function is called correctly.""" for trait_type, thresh, trait_name, dataset_name, columns, table, expected in [ @@ -42,6 +44,7 @@ class TestDatasetsDBFunctions(TestCase): table=table, cols=columns), {"threshold": thresh, "name": dataset_name}) + @pytest.mark.unit_test def test_retrieve_probeset_group_fields(self): """ Test that the `group` and `group_id` fields are retrieved appropriately @@ -65,6 +68,7 @@ class TestDatasetsDBFunctions(TestCase): " AND ProbeSetFreeze.Name = %(name)s"), {"name": trait_name}) + @pytest.mark.unit_test def test_retrieve_group_fields(self): """ Test that the group fields are set up correctly for the different trait @@ -90,6 +94,7 @@ class TestDatasetsDBFunctions(TestCase): trait_type, trait_name, dataset_info, db_mock), expected) + @pytest.mark.unit_test def test_retrieve_publish_group_fields(self): """ Test that the `group` and `group_id` fields are retrieved appropriately @@ -112,6 +117,7 @@ class TestDatasetsDBFunctions(TestCase): " AND PublishFreeze.Name = %(name)s"), {"name": trait_name}) + @pytest.mark.unit_test def test_retrieve_geno_group_fields(self): """ Test that the `group` and `group_id` fields are retrieved appropriately diff --git a/tests/unit/db/test_db.py b/tests/unit/db/test_db.py index e47c9fd..8ac468c 100644 --- a/tests/unit/db/test_db.py +++ b/tests/unit/db/test_db.py @@ -2,6 +2,8 @@ from unittest import TestCase from unittest import mock +import pytest + from gn3.db import fetchall from gn3.db import fetchone from gn3.db import update @@ -14,6 +16,7 @@ from gn3.db.metadata_audit import MetadataAudit class TestCrudMethods(TestCase): """Test cases for CRUD methods""" + @pytest.mark.unit_test def test_update_phenotype_with_no_data(self): """Test that a phenotype is updated correctly if an empty Phenotype dataclass is provided @@ -24,6 +27,7 @@ class TestCrudMethods(TestCase): conn=db_mock, table="Phenotype", data=Phenotype(), where=Phenotype()), None) + @pytest.mark.unit_test def test_update_phenotype_with_data(self): """ Test that a phenotype is updated correctly if some @@ -46,6 +50,7 @@ class TestCrudMethods(TestCase): "Submitter = %s WHERE id = %s AND Owner = %s", ('Test Pre Pub', 'Test Post Pub', 'Rob', 1, 'Rob')) + @pytest.mark.unit_test def test_fetch_phenotype(self): """Test that a single phenotype is fetched properly @@ -68,6 +73,7 @@ class TestCrudMethods(TestCase): "SELECT * FROM Phenotype WHERE id = %s AND Owner = %s", (35, 'Rob')) + @pytest.mark.unit_test def test_fetchall_metadataaudit(self): """Test that multiple metadata_audit entries are fetched properly @@ -96,6 +102,7 @@ class TestCrudMethods(TestCase): "dataset_id = %s AND editor = %s"), (35, 'Rob')) + @pytest.mark.unit_test # pylint: disable=R0201 def test_probeset_called_with_right_columns(self): """Given a columns argument, test that the correct sql query is @@ -112,6 +119,7 @@ class TestCrudMethods(TestCase): "Name = %s", ("1446112_at",)) + @pytest.mark.unit_test def test_diff_from_dict(self): """Test that a correct diff is generated""" self.assertEqual(diff_from_dict({"id": 1, "data": "a"}, diff --git a/tests/unit/db/test_genotypes.py b/tests/unit/db/test_genotypes.py index c125224..28728bf 100644 --- a/tests/unit/db/test_genotypes.py +++ b/tests/unit/db/test_genotypes.py @@ -1,5 +1,6 @@ """Tests gn3.db.genotypes""" from unittest import TestCase +import pytest from gn3.db.genotypes import ( parse_genotype_file, parse_genotype_labels, @@ -10,6 +11,7 @@ from gn3.db.genotypes import ( class TestGenotypes(TestCase): """Tests for functions in `gn3.db.genotypes`.""" + @pytest.mark.unit_test def test_parse_genotype_labels(self): """Test that the genotype labels are parsed correctly.""" self.assertEqual( @@ -22,6 +24,7 @@ class TestGenotypes(TestCase): ("type", "test_type"), ("mat", "test_mat"), ("pat", "test_pat"), ("het", "test_het"), ("unk", "test_unk"))) + @pytest.mark.unit_test def test_parse_genotype_header(self): """Test that the genotype header is parsed correctly.""" for header, expected in [ @@ -43,6 +46,7 @@ class TestGenotypes(TestCase): with self.subTest(header=header): self.assertEqual(parse_genotype_header(header), expected) + @pytest.mark.unit_test def test_parse_genotype_data_line(self): """Test parsing of data lines.""" for line, geno_obj, parlist, expected in [ @@ -76,6 +80,7 @@ class TestGenotypes(TestCase): parse_genotype_marker(line, geno_obj, parlist), expected) + @pytest.mark.unit_test def test_build_genotype_chromosomes(self): """ Given `markers` and `geno_obj`, test that `build_genotype_chromosomes` @@ -115,6 +120,7 @@ class TestGenotypes(TestCase): build_genotype_chromosomes(geno_obj, markers), expected) + @pytest.mark.unit_test def test_parse_genotype_file(self): """Test the parsing of genotype files. """ self.assertEqual( diff --git a/tests/unit/db/test_species.py b/tests/unit/db/test_species.py index b2c4844..e883b21 100644 --- a/tests/unit/db/test_species.py +++ b/tests/unit/db/test_species.py @@ -2,6 +2,8 @@ from unittest import TestCase from unittest import mock +import pytest + from gn3.db.species import get_chromosome from gn3.db.species import get_all_species @@ -9,6 +11,7 @@ from gn3.db.species import get_all_species class TestChromosomes(TestCase): """Test cases for fetching chromosomes""" + @pytest.mark.unit_test def test_get_chromosome_using_species_name(self): """Test that the chromosome is fetched using a species name""" db_mock = mock.MagicMock() @@ -24,6 +27,7 @@ class TestChromosomes(TestCase): "Species.Name = 'TestCase' ORDER BY OrderId" ) + @pytest.mark.unit_test def test_get_chromosome_using_group_name(self): """Test that the chromosome is fetched using a group name""" db_mock = mock.MagicMock() @@ -39,6 +43,7 @@ class TestChromosomes(TestCase): "InbredSet.Name = 'TestCase' ORDER BY OrderId" ) + @pytest.mark.unit_test def test_get_all_species(self): """Test that species are fetched correctly""" db_mock = mock.MagicMock() diff --git a/tests/unit/db/test_traits.py b/tests/unit/db/test_traits.py index f3e0bab..d7c0b27 100644 --- a/tests/unit/db/test_traits.py +++ b/tests/unit/db/test_traits.py @@ -1,5 +1,6 @@ """Tests for gn3/db/traits.py""" from unittest import mock, TestCase +import pytest from gn3.db.traits import ( build_trait_name, export_trait_data, @@ -49,6 +50,7 @@ trait_data = { class TestTraitsDBFunctions(TestCase): "Test cases for traits functions" + @pytest.mark.unit_test def test_retrieve_publish_trait_info(self): """Test retrieval of type `Publish` traits.""" db_mock = mock.MagicMock() @@ -83,6 +85,7 @@ class TestTraitsDBFunctions(TestCase): " AND PublishXRef.InbredSetId = %(trait_dataset_id)s"), trait_source) + @pytest.mark.unit_test def test_retrieve_probeset_trait_info(self): """Test retrieval of type `Probeset` traits.""" db_mock = mock.MagicMock() @@ -118,6 +121,7 @@ class TestTraitsDBFunctions(TestCase): "AND ProbeSetFreeze.Name = %(trait_dataset_name)s " "AND ProbeSet.Name = %(trait_name)s"), trait_source) + @pytest.mark.unit_test def test_retrieve_geno_trait_info(self): """Test retrieval of type `Geno` traits.""" db_mock = mock.MagicMock() @@ -141,6 +145,7 @@ class TestTraitsDBFunctions(TestCase): "AND Geno.Name = %(trait_name)s"), trait_source) + @pytest.mark.unit_test def test_retrieve_temp_trait_info(self): """Test retrieval of type `Temp` traits.""" db_mock = mock.MagicMock() @@ -153,6 +158,7 @@ class TestTraitsDBFunctions(TestCase): "SELECT name, description FROM Temp WHERE Name = %(trait_name)s", trait_source) + @pytest.mark.unit_test def test_build_trait_name_with_good_fullnames(self): """ Check that the name is built correctly. @@ -169,6 +175,7 @@ class TestTraitsDBFunctions(TestCase): with self.subTest(fullname=fullname): self.assertEqual(build_trait_name(fullname), expected) + @pytest.mark.unit_test def test_build_trait_name_with_bad_fullnames(self): """ Check that an exception is raised if the full name format is wrong. @@ -178,6 +185,7 @@ class TestTraitsDBFunctions(TestCase): with self.assertRaises(AssertionError, msg="Name format error"): build_trait_name(fullname) + @pytest.mark.unit_test def test_retrieve_trait_info(self): """Test that information on traits is retrieved as appropriate.""" for threshold, trait_fullname, expected in [ @@ -194,6 +202,7 @@ class TestTraitsDBFunctions(TestCase): threshold, trait_fullname, db_mock), expected) + @pytest.mark.unit_test def test_update_sample_data(self): """Test that the SQL queries when calling update_sample_data are called with the right calls. @@ -242,6 +251,7 @@ class TestTraitsDBFunctions(TestCase): mock.call(N_STRAIN_SQL, (2, 1, 1))] ) + @pytest.mark.unit_test def test_set_haveinfo_field(self): """Test that the `haveinfo` field is set up correctly""" for trait_info, expected in [ @@ -250,6 +260,7 @@ class TestTraitsDBFunctions(TestCase): with self.subTest(trait_info=trait_info, expected=expected): self.assertEqual(set_haveinfo_field(trait_info), expected) + @pytest.mark.unit_test def test_set_homologene_id_field(self): """Test that the `homologene_id` field is set up correctly""" for trait_type, trait_info, expected in [ @@ -264,6 +275,7 @@ class TestTraitsDBFunctions(TestCase): self.assertEqual( set_homologene_id_field(trait_type, trait_info, db_mock), expected) + @pytest.mark.unit_test def test_set_confidential_field(self): """Test that the `confidential` field is set up correctly""" for trait_type, trait_info, expected in [ @@ -275,6 +287,7 @@ class TestTraitsDBFunctions(TestCase): self.assertEqual( set_confidential_field(trait_type, trait_info), expected) + @pytest.mark.unit_test def test_export_trait_data_dtype(self): """ Test `export_trait_data` with different values for the `dtype` keyword @@ -290,6 +303,7 @@ class TestTraitsDBFunctions(TestCase): export_trait_data(trait_data, samplelist, dtype=dtype), expected) + @pytest.mark.unit_test def test_export_trait_data_dtype_all_flags(self): """ Test `export_trait_data` with different values for the `dtype` keyword @@ -331,6 +345,7 @@ class TestTraitsDBFunctions(TestCase): n_exists=nflag), expected) + @pytest.mark.unit_test def test_export_informative(self): """Test that the function exports appropriate data.""" # pylint: disable=W0621 diff --git a/tests/unit/test_authentication.py b/tests/unit/test_authentication.py index 061b684..59c88ef 100644 --- a/tests/unit/test_authentication.py +++ b/tests/unit/test_authentication.py @@ -1,8 +1,10 @@ """Test cases for authentication.py""" import json import unittest - from unittest import mock + +import pytest + from gn3.authentication import AdminRole from gn3.authentication import DataRole from gn3.authentication import get_highest_user_access_role @@ -24,6 +26,7 @@ class TestGetUserMembership(unittest.TestCase): '"created_timestamp": "Oct 06 2021 06:39PM"}')} self.conn = conn + @pytest.mark.unit_test def test_user_is_group_member_only(self): """Test that a user is only a group member""" self.assertEqual( @@ -34,6 +37,7 @@ class TestGetUserMembership(unittest.TestCase): {"member": True, "admin": False}) + @pytest.mark.unit_test def test_user_is_group_admin_only(self): """Test that a user is a group admin only""" self.assertEqual( @@ -44,6 +48,7 @@ class TestGetUserMembership(unittest.TestCase): {"member": False, "admin": True}) + @pytest.mark.unit_test 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( @@ -58,6 +63,7 @@ class TestGetUserMembership(unittest.TestCase): class TestCheckUserAccessRole(unittest.TestCase): """Test cases for `get_highest_user_access_role`""" + @pytest.mark.unit_test @mock.patch("gn3.authentication.requests.get") def test_edit_access(self, requests_mock): """Test that the right access roles are set if the user has edit access""" @@ -79,6 +85,7 @@ class TestCheckUserAccessRole(unittest.TestCase): "admin": AdminRole.EDIT_ACCESS, }) + @pytest.mark.unit_test @mock.patch("gn3.authentication.requests.get") def test_no_access(self, requests_mock): """Test that the right access roles are set if the user has no access""" diff --git a/tests/unit/test_commands.py b/tests/unit/test_commands.py index e644e1a..e0efaf7 100644 --- a/tests/unit/test_commands.py +++ b/tests/unit/test_commands.py @@ -5,6 +5,7 @@ from dataclasses import dataclass from datetime import datetime from typing import Callable from unittest import mock +import pytest from gn3.commands import compose_gemma_cmd from gn3.commands import compose_rqtl_cmd from gn3.commands import queue_cmd @@ -23,6 +24,7 @@ class MockRedis: class TestCommands(unittest.TestCase): """Test cases for commands.py""" + @pytest.mark.unit_test def test_compose_gemma_cmd_no_extra_args(self): """Test that the gemma cmd is composed correctly""" self.assertEqual( @@ -37,6 +39,7 @@ class TestCommands(unittest.TestCase): "-p /tmp/gf13Ad0tRX/phenofile.txt" " -gk")) + @pytest.mark.unit_test def test_compose_gemma_cmd_extra_args(self): """Test that the gemma cmd is composed correctly""" self.assertEqual( @@ -54,6 +57,7 @@ class TestCommands(unittest.TestCase): "-p /tmp/gf13Ad0tRX/phenofile.txt" " -gk")) + @pytest.mark.unit_test def test_compose_rqtl_cmd(self): """Test that the R/qtl cmd is composed correctly""" self.assertEqual( @@ -78,6 +82,7 @@ class TestCommands(unittest.TestCase): "--addcovar") ) + @pytest.mark.unit_test def test_queue_cmd_exception_raised_when_redis_is_down(self): """Test that the correct error is raised when Redis is unavailable""" self.assertRaises(RedisConnectionError, @@ -88,6 +93,7 @@ class TestCommands(unittest.TestCase): hset=mock.MagicMock(), rpush=mock.MagicMock())) + @pytest.mark.unit_test @mock.patch("gn3.commands.datetime") @mock.patch("gn3.commands.uuid4") def test_queue_cmd_correct_calls_to_redis(self, mock_uuid4, @@ -112,6 +118,7 @@ class TestCommands(unittest.TestCase): mock_redis_conn.rpush.assert_has_calls( [mock.call("GN2::job-queue", actual_unique_id)]) + @pytest.mark.unit_test @mock.patch("gn3.commands.datetime") @mock.patch("gn3.commands.uuid4") def test_queue_cmd_right_calls_to_redis_with_email(self, @@ -140,11 +147,13 @@ class TestCommands(unittest.TestCase): mock_redis_conn.rpush.assert_has_calls( [mock.call("GN2::job-queue", actual_unique_id)]) + @pytest.mark.unit_test def test_run_cmd_correct_input(self): """Test that a correct cmd is processed correctly""" self.assertEqual(run_cmd("echo test"), {"code": 0, "output": "test\n"}) + @pytest.mark.unit_test def test_run_cmd_incorrect_input(self): """Test that an incorrect cmd is processed correctly""" result = run_cmd("echoo test") diff --git a/tests/unit/test_data_helpers.py b/tests/unit/test_data_helpers.py index 88ea469..b6de42e 100644 --- a/tests/unit/test_data_helpers.py +++ b/tests/unit/test_data_helpers.py @@ -4,6 +4,8 @@ Test functions in gn3.data_helpers from unittest import TestCase +import pytest + from gn3.data_helpers import partition_by, partition_all, parse_csv_line class TestDataHelpers(TestCase): @@ -11,6 +13,7 @@ class TestDataHelpers(TestCase): Test functions in gn3.data_helpers """ + @pytest.mark.unit_test def test_partition_all(self): """ Test that `gn3.data_helpers.partition_all` partitions sequences as expected. @@ -36,6 +39,7 @@ class TestDataHelpers(TestCase): with self.subTest(n=count, items=items): self.assertEqual(partition_all(count, items), expected) + @pytest.mark.unit_test def test_parse_csv_line(self): """ Test parsing a single line from a CSV file @@ -60,6 +64,7 @@ class TestDataHelpers(TestCase): line=line, delimiter=delimiter, quoting=quoting), expected) + @pytest.mark.unit_test def test_partition_by(self): """ Test that `partition_by` groups the data using the given predicate diff --git a/tests/unit/test_db_utils.py b/tests/unit/test_db_utils.py index 0f2de9e..dd0cd5d 100644 --- a/tests/unit/test_db_utils.py +++ b/tests/unit/test_db_utils.py @@ -3,6 +3,7 @@ from unittest import TestCase from unittest import mock +import pytest from types import SimpleNamespace from gn3.db_utils import database_connector @@ -12,6 +13,7 @@ from gn3.db_utils import parse_db_url class TestDatabase(TestCase): """class contains testd for db connection functions""" + @pytest.mark.unit_test @mock.patch("gn3.db_utils.mdb") @mock.patch("gn3.db_utils.parse_db_url") def test_database_connector(self, mock_db_parser, mock_sql): @@ -28,6 +30,7 @@ class TestDatabase(TestCase): self.assertIsInstance( results, tuple, "database not created successfully") + @pytest.mark.unit_test @mock.patch("gn3.db_utils.SQL_URI", "mysql://username:4321@localhost/test") def test_parse_db_url(self): diff --git a/tests/unit/test_file_utils.py b/tests/unit/test_file_utils.py index 75be4f6..77fea88 100644 --- a/tests/unit/test_file_utils.py +++ b/tests/unit/test_file_utils.py @@ -5,6 +5,7 @@ import unittest from dataclasses import dataclass from typing import Callable from unittest import mock +import pytest from gn3.fs_helpers import extract_uploaded_file from gn3.fs_helpers import get_dir_hash from gn3.fs_helpers import jsonfile_to_dict @@ -21,17 +22,20 @@ class MockFile: class TestFileUtils(unittest.TestCase): """Test cases for procedures defined in fs_helpers.py""" + @pytest.mark.unit_test def test_get_dir_hash(self): """Test that a directory is hashed correctly""" test_dir = os.path.join(os.path.dirname(__file__), "test_data") self.assertEqual("3aeafab7d53b4f76d223366ae7ee9738", get_dir_hash(test_dir)) + @pytest.mark.unit_test def test_get_dir_hash_non_existent_dir(self): """Test thata an error is raised when the dir does not exist""" self.assertRaises(FileNotFoundError, get_dir_hash, "/non-existent-file") + @pytest.mark.unit_test def test_jsonfile_to_dict(self): """Test that a json file is parsed correctly""" "" json_file = os.path.join(os.path.dirname(__file__), "test_data", @@ -39,12 +43,14 @@ class TestFileUtils(unittest.TestCase): self.assertEqual("Longer description", jsonfile_to_dict(json_file).get("description")) + @pytest.mark.unit_test def test_jsonfile_to_dict_nonexistent_file(self): """Test that a ValueError is raised when the json file is non-existent""" self.assertRaises(FileNotFoundError, jsonfile_to_dict, "/non-existent-dir") + @pytest.mark.unit_test @mock.patch("gn3.fs_helpers.tarfile") @mock.patch("gn3.fs_helpers.secure_filename") def test_extract_uploaded_file(self, mock_file, mock_tarfile): @@ -65,6 +71,7 @@ non-existent""" mock_file.assert_called_once_with("upload-data.tar.gz") self.assertEqual(result, {"status": 0, "token": "abcdef-abcdef"}) + @pytest.mark.unit_test @mock.patch("gn3.fs_helpers.secure_filename") def test_extract_uploaded_file_non_existent_gzip(self, mock_file): """Test that the right error message is returned when there is a problem @@ -78,6 +85,7 @@ extracting the file""" "error": "gzip failed to unpack file" }) + @pytest.mark.unit_test def test_cache_ipfs_file_cache_hit(self): """Test that the correct file location is returned if there's a cache hit""" # Create empty file @@ -96,6 +104,7 @@ extracting the file""" os.rmdir(test_dir) self.assertEqual(file_loc, f"{test_dir}/genotype.txt") + @pytest.mark.unit_test @mock.patch("gn3.fs_helpers.ipfshttpclient") def test_cache_ipfs_file_cache_miss(self, mock_ipfs): diff --git a/tests/unit/test_heatmaps.py b/tests/unit/test_heatmaps.py index a88341b..8781d6f 100644 --- a/tests/unit/test_heatmaps.py +++ b/tests/unit/test_heatmaps.py @@ -1,6 +1,7 @@ """Module contains tests for gn3.heatmaps.heatmaps""" from unittest import TestCase +import pytest from numpy.testing import assert_allclose from gn3.heatmaps import ( @@ -27,6 +28,7 @@ slinked = ( class TestHeatmap(TestCase): """Class for testing heatmap computation functions""" + @pytest.mark.unit_test def test_cluster_traits(self): # pylint: disable=R0201 """ Test that the clustering is working as expected. @@ -76,11 +78,13 @@ class TestHeatmap(TestCase): 1.7413442197913358, 0.33370067057028485, 1.3256191648260216, 0.0))) + @pytest.mark.unit_test def test_compute_heatmap_order(self): """Test the orders.""" self.assertEqual( compute_traits_order(slinked), (0, 2, 1, 7, 5, 9, 3, 6, 8, 4)) + @pytest.mark.unit_test def test_retrieve_samples_and_values(self): """Test retrieval of samples and values.""" for orders, slist, tdata, expected in [ @@ -106,6 +110,7 @@ class TestHeatmap(TestCase): self.assertEqual( retrieve_samples_and_values(orders, slist, tdata), expected) + @pytest.mark.unit_test def test_get_lrs_from_chr(self): """Check that function gets correct LRS values""" for trait, chromosome, expected in [ @@ -120,6 +125,7 @@ class TestHeatmap(TestCase): with self.subTest(trait=trait, chromosome=chromosome): self.assertEqual(get_lrs_from_chr(trait, chromosome), expected) + @pytest.mark.unit_test def test_process_traits_data_for_heatmap(self): """Check for correct processing of data for heatmap generation.""" self.assertEqual( @@ -132,6 +138,7 @@ class TestHeatmap(TestCase): [[0.5, 0.579, 0.5], [0.5, 0.5, 0.5]]]) + @pytest.mark.unit_test def test_get_loci_names(self): """Check that loci names are retrieved correctly.""" for organised, expected in ( |