From d3458f207061116b09192317adf9ab1e7c6040b1 Mon Sep 17 00:00:00 2001 From: Sander Roet Date: Wed, 28 Feb 2024 16:29:27 +0100 Subject: [PATCH 01/14] restructure test_tmjob to hit all lines --- tests/test_tmjob.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_tmjob.py b/tests/test_tmjob.py index 89721120..dfdca903 100644 --- a/tests/test_tmjob.py +++ b/tests/test_tmjob.py @@ -141,6 +141,7 @@ def test_tm_job_errors(self): with self.assertRaises(ValueError, msg='Invalid start index in search should raise ValueError'): TMJob('0', 10, TEST_TOMOGRAM, TEST_TEMPLATE, TEST_MASK, TEST_DATA_DIR, voxel_size=1., **{param: [-10, 100]}) + with self.assertRaises(ValueError, msg='Invalid start index in search should raise ValueError'): TMJob('0', 10, TEST_TOMOGRAM, TEST_TEMPLATE, TEST_MASK, TEST_DATA_DIR, voxel_size=1., **{param: [110, 130]}) with self.assertRaises(ValueError, msg='Invalid end index in search should raise ValueError'): From 697250e0f4b1a1cd2c2e63fcde152e9d269438bc Mon Sep 17 00:00:00 2001 From: Sander Roet Date: Wed, 28 Feb 2024 16:39:26 +0100 Subject: [PATCH 02/14] fix missing line hits test_weight --- tests/test_weights.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/test_weights.py b/tests/test_weights.py index abeaeb32..5e197694 100644 --- a/tests/test_weights.py +++ b/tests/test_weights.py @@ -114,6 +114,9 @@ def test_radial_reduced_grid(self): with self.assertRaises(ValueError, msg='Radial reduced grid should raise ValueError if the shape is ' 'not 2- or 3-dimensional.'): radial_reduced_grid((5, )) + with self.assertRaises(ValueError, msg='Radial reduced grid should raise ValueError if the shape is ' + 'not 2- or 3-dimensional.'): + radial_reduced_grid((5, ) * 4) self.assertEqual(radial_reduced_grid(self.volume_shape_even).shape, self.reduced_even_shape_3d, @@ -291,6 +294,9 @@ def test_power_spectrum_profile(self): with self.assertRaises(ValueError, msg='Power spectrum profile should raise ValueError if input image is ' 'not 2- or 3-dimensional.'): power_spectrum_profile(np.zeros(5)) + with self.assertRaises(ValueError, msg='Power spectrum profile should raise ValueError if input image is ' + 'not 2- or 3-dimensional.'): + power_spectrum_profile(np.zeros((5, ) * 4)) profile = power_spectrum_profile(np.zeros(self.volume_shape_irregular)) self.assertEqual(profile.shape, (max(self.volume_shape_irregular) // 2 + 1, ), @@ -305,6 +311,8 @@ def test_profile_to_weighting(self): with self.assertRaises(ValueError, msg='Profile to weighting should raise a ValueError if the output shape ' 'for the weighting is not 2- or 3-dimensional.'): profile_to_weighting(np.zeros(5), (5, )) + with self.assertRaises(ValueError, msg='Profile to weighting should raise a ValueError if the output shape ' + 'for the weighting is not 2- or 3-dimensional.'): profile_to_weighting(np.zeros(5), (5,) * 4) profile = power_spectrum_profile(np.zeros(self.volume_shape_irregular)) From 3711063f2819ba047905c42aebbb58a1a071c2ef Mon Sep 17 00:00:00 2001 From: Sander Roet Date: Wed, 28 Feb 2024 16:39:59 +0100 Subject: [PATCH 03/14] test that the other tests would not test that binscript if plotting is not available --- tests/test_broken_imports.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/test_broken_imports.py b/tests/test_broken_imports.py index a4fca053..b09b5af7 100644 --- a/tests/test_broken_imports.py +++ b/tests/test_broken_imports.py @@ -62,6 +62,9 @@ def test_missing_matplotlib(self): # assert that importing the plotting module fails completely with self.assertRaisesRegex(RuntimeError, "matplotlib and seaborn"): reload(pytom_tm.plotting) + # test that entry point testing still works + tested_entry_points = [i[0] for i in reload(.test_entry_points).ENTRY_POINTS_TO_TEST + self.assertNotIn('pytom_estimate_roc.py', tested_entry_points) def test_missing_seaborn(self): # assert working import @@ -81,5 +84,7 @@ def test_missing_seaborn(self): with self.assertRaisesRegex(RuntimeError, "matplotlib and seaborn"): reload(pytom_tm.plotting) - + # test that entry point testing still works + tested_entry_points = [i[0] for i in reload(.test_entry_points).ENTRY_POINTS_TO_TEST + self.assertNotIn('pytom_estimate_roc.py', tested_entry_points) From 6d628fd8633562f19b1e1bc82594024b189b1bcf Mon Sep 17 00:00:00 2001 From: Sander Roet Date: Wed, 28 Feb 2024 16:42:37 +0100 Subject: [PATCH 04/14] exclude coverage for uncoverable line --- tests/test00_parallel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test00_parallel.py b/tests/test00_parallel.py index e51ba4e3..4aeb3123 100644 --- a/tests/test00_parallel.py +++ b/tests/test00_parallel.py @@ -77,7 +77,7 @@ def test_parallel_breaking(self): self.assertEqual(len(multiprocessing.active_children()), 0, msg='a process was still lingering after a parallel job with partially invalid resources ' 'was started') - else: + else: # pragma: no cover self.fail('This should have given a RuntimeError') def test_parallel_manager(self): From 5d0dafc519da22fc5baa5d3306376320cca44dba Mon Sep 17 00:00:00 2001 From: Sander Roet Date: Wed, 28 Feb 2024 16:44:17 +0100 Subject: [PATCH 05/14] try different syntax --- tests/test_broken_imports.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_broken_imports.py b/tests/test_broken_imports.py index b09b5af7..626a9e9a 100644 --- a/tests/test_broken_imports.py +++ b/tests/test_broken_imports.py @@ -63,7 +63,7 @@ def test_missing_matplotlib(self): with self.assertRaisesRegex(RuntimeError, "matplotlib and seaborn"): reload(pytom_tm.plotting) # test that entry point testing still works - tested_entry_points = [i[0] for i in reload(.test_entry_points).ENTRY_POINTS_TO_TEST + tested_entry_points = [i[0] for i in reload(test_entry_points).ENTRY_POINTS_TO_TEST] self.assertNotIn('pytom_estimate_roc.py', tested_entry_points) def test_missing_seaborn(self): @@ -85,6 +85,6 @@ def test_missing_seaborn(self): reload(pytom_tm.plotting) # test that entry point testing still works - tested_entry_points = [i[0] for i in reload(.test_entry_points).ENTRY_POINTS_TO_TEST + tested_entry_points = [i[0] for i in reload(test_entry_points).ENTRY_POINTS_TO_TEST] self.assertNotIn('pytom_estimate_roc.py', tested_entry_points) From ab6d27263d9b6684cf7385d98b944519cdbeb26e Mon Sep 17 00:00:00 2001 From: Sander Roet Date: Wed, 28 Feb 2024 16:50:55 +0100 Subject: [PATCH 06/14] try this syntax instead? --- tests/test_broken_imports.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_broken_imports.py b/tests/test_broken_imports.py index 626a9e9a..b4b022d5 100644 --- a/tests/test_broken_imports.py +++ b/tests/test_broken_imports.py @@ -63,7 +63,7 @@ def test_missing_matplotlib(self): with self.assertRaisesRegex(RuntimeError, "matplotlib and seaborn"): reload(pytom_tm.plotting) # test that entry point testing still works - tested_entry_points = [i[0] for i in reload(test_entry_points).ENTRY_POINTS_TO_TEST] + tested_entry_points = [i[0] for i in reload(.test_entry_points).ENTRY_POINTS_TO_TEST] self.assertNotIn('pytom_estimate_roc.py', tested_entry_points) def test_missing_seaborn(self): @@ -85,6 +85,6 @@ def test_missing_seaborn(self): reload(pytom_tm.plotting) # test that entry point testing still works - tested_entry_points = [i[0] for i in reload(test_entry_points).ENTRY_POINTS_TO_TEST] + tested_entry_points = [i[0] for i in reload(.test_entry_points).ENTRY_POINTS_TO_TEST] self.assertNotIn('pytom_estimate_roc.py', tested_entry_points) From 89a4e525050d4ba67304f50abe0bcddff0fc1c91 Mon Sep 17 00:00:00 2001 From: Sander Roet Date: Wed, 28 Feb 2024 16:57:27 +0100 Subject: [PATCH 07/14] use documented way instead --- tests/test_broken_imports.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/test_broken_imports.py b/tests/test_broken_imports.py index b4b022d5..871d783f 100644 --- a/tests/test_broken_imports.py +++ b/tests/test_broken_imports.py @@ -45,7 +45,8 @@ def test_broken_cupy(self): def test_missing_matplotlib(self): # assert working import import pytom_tm - + import .test_entry_points as tep + matplotlib_not_found = module_not_found_mock('matplotlib.pyplot') with unittest.mock.patch('builtins.__import__', side_effect=matplotlib_not_found): with self.assertRaisesRegex(ModuleNotFoundError, 'matplotlib'): @@ -63,12 +64,14 @@ def test_missing_matplotlib(self): with self.assertRaisesRegex(RuntimeError, "matplotlib and seaborn"): reload(pytom_tm.plotting) # test that entry point testing still works - tested_entry_points = [i[0] for i in reload(.test_entry_points).ENTRY_POINTS_TO_TEST] + tested_entry_points = [i[0] for i in reload(tep).ENTRY_POINTS_TO_TEST] self.assertNotIn('pytom_estimate_roc.py', tested_entry_points) def test_missing_seaborn(self): # assert working import import pytom_tm + # needed for test test later on + import .test_entry_points as tep seaborn_not_found = module_not_found_mock('seaborn') with unittest.mock.patch('builtins.__import__', side_effect=seaborn_not_found): @@ -85,6 +88,6 @@ def test_missing_seaborn(self): reload(pytom_tm.plotting) # test that entry point testing still works - tested_entry_points = [i[0] for i in reload(.test_entry_points).ENTRY_POINTS_TO_TEST] + tested_entry_points = [i[0] for i in reload(tep).ENTRY_POINTS_TO_TEST] self.assertNotIn('pytom_estimate_roc.py', tested_entry_points) From 9c52771402c2b4be5e3104e60c406b4dd137d4d5 Mon Sep 17 00:00:00 2001 From: Sander Roet Date: Wed, 28 Feb 2024 17:03:23 +0100 Subject: [PATCH 08/14] use non-relative import instead? --- tests/test_broken_imports.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_broken_imports.py b/tests/test_broken_imports.py index 871d783f..94c14952 100644 --- a/tests/test_broken_imports.py +++ b/tests/test_broken_imports.py @@ -45,7 +45,7 @@ def test_broken_cupy(self): def test_missing_matplotlib(self): # assert working import import pytom_tm - import .test_entry_points as tep + import test_entry_points as tep matplotlib_not_found = module_not_found_mock('matplotlib.pyplot') with unittest.mock.patch('builtins.__import__', side_effect=matplotlib_not_found): @@ -71,7 +71,7 @@ def test_missing_seaborn(self): # assert working import import pytom_tm # needed for test test later on - import .test_entry_points as tep + import test_entry_points as tep seaborn_not_found = module_not_found_mock('seaborn') with unittest.mock.patch('builtins.__import__', side_effect=seaborn_not_found): From a31163bf4ca817868b98d034cdfa31de3cab5d5b Mon Sep 17 00:00:00 2001 From: Sander Roet Date: Thu, 29 Feb 2024 14:22:38 +0100 Subject: [PATCH 09/14] revert changes to test_broken_imports.py --- tests/test_broken_imports.py | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/tests/test_broken_imports.py b/tests/test_broken_imports.py index 94c14952..a4fca053 100644 --- a/tests/test_broken_imports.py +++ b/tests/test_broken_imports.py @@ -45,8 +45,7 @@ def test_broken_cupy(self): def test_missing_matplotlib(self): # assert working import import pytom_tm - import test_entry_points as tep - + matplotlib_not_found = module_not_found_mock('matplotlib.pyplot') with unittest.mock.patch('builtins.__import__', side_effect=matplotlib_not_found): with self.assertRaisesRegex(ModuleNotFoundError, 'matplotlib'): @@ -63,15 +62,10 @@ def test_missing_matplotlib(self): # assert that importing the plotting module fails completely with self.assertRaisesRegex(RuntimeError, "matplotlib and seaborn"): reload(pytom_tm.plotting) - # test that entry point testing still works - tested_entry_points = [i[0] for i in reload(tep).ENTRY_POINTS_TO_TEST] - self.assertNotIn('pytom_estimate_roc.py', tested_entry_points) def test_missing_seaborn(self): # assert working import import pytom_tm - # needed for test test later on - import test_entry_points as tep seaborn_not_found = module_not_found_mock('seaborn') with unittest.mock.patch('builtins.__import__', side_effect=seaborn_not_found): @@ -87,7 +81,5 @@ def test_missing_seaborn(self): with self.assertRaisesRegex(RuntimeError, "matplotlib and seaborn"): reload(pytom_tm.plotting) - # test that entry point testing still works - tested_entry_points = [i[0] for i in reload(tep).ENTRY_POINTS_TO_TEST] - self.assertNotIn('pytom_estimate_roc.py', tested_entry_points) + From 8086a2e6f2b23f60661a2114fd9645f63107c270 Mon Sep 17 00:00:00 2001 From: Sander Roet Date: Thu, 29 Feb 2024 14:27:35 +0100 Subject: [PATCH 10/14] actually run test without the plotting code enabled --- .github/workflows/unit-tests.yml | 11 +++++++++-- pyproject.toml | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 0d63469e..c9814837 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -27,11 +27,18 @@ jobs: run: | conda install -y -c conda-forge python=3 cupy cuda-version=11.8 python -m pip install coverage - - name: Install code and list dependencies + - name: Install base code and list dependencies + run: | + python -m pip install -e . + conda list + - name: Run tests + run: | + coverage run -m unittest discover tests/ + - name: Install plotting code and list dependencies run: | python -m pip install -e .[plotting] conda list - - name: Run tests and generate coverage + - name: Run complete tests and generate coverage report run: | coverage run -m unittest discover tests/ coverage combine diff --git a/pyproject.toml b/pyproject.toml index f55d7b7a..431b4ae3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -61,3 +61,4 @@ package-data = {"pytom_tm.angle_lists" = ["*.txt"]} [tool.coverage.run] concurrency = ["multiprocessing", "thread"] +parallel-mode = true From 72ba170c56ac44435446b7fa6bc85ef048f562ee Mon Sep 17 00:00:00 2001 From: Sander Roet Date: Thu, 29 Feb 2024 14:40:23 +0100 Subject: [PATCH 11/14] skip test if plotting is not available --- tests/test_broken_imports.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/test_broken_imports.py b/tests/test_broken_imports.py index a4fca053..48f00e93 100644 --- a/tests/test_broken_imports.py +++ b/tests/test_broken_imports.py @@ -4,6 +4,13 @@ # Mock out installed dependencies orig_import = __import__ +# skip tests if optional stuff is not installed +SKIP_PLOT = False +try: + import pytom_tm.plotting +except ModuleNotFoundError: + SKIP_PLOT = True + def module_not_found_mock(missing_name): def import_mock(name, *args): if name == missing_name: @@ -42,6 +49,7 @@ def test_broken_cupy(self): self.assertEqual(len(cm.output), 1) self.assertIn("cupy installation not found or not functional", cm.output[0]) + @unittest.skipIf(SKIP_PLOT, "plotting module not installed") def test_missing_matplotlib(self): # assert working import import pytom_tm @@ -63,6 +71,7 @@ def test_missing_matplotlib(self): with self.assertRaisesRegex(RuntimeError, "matplotlib and seaborn"): reload(pytom_tm.plotting) + @unittest.skipIf(SKIP_PLOT, "plotting module not installed") def test_missing_seaborn(self): # assert working import import pytom_tm From c5321d577b14edc3d9fe9f4bc904c7147a9e088a Mon Sep 17 00:00:00 2001 From: Sander Roet Date: Thu, 29 Feb 2024 14:48:54 +0100 Subject: [PATCH 12/14] use correct pyroject.toml flag for parellel unittest --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 431b4ae3..4dc3293a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -61,4 +61,4 @@ package-data = {"pytom_tm.angle_lists" = ["*.txt"]} [tool.coverage.run] concurrency = ["multiprocessing", "thread"] -parallel-mode = true +parallel = true From 27f0185fbbf93545a2c5b7253810984c003bf51c Mon Sep 17 00:00:00 2001 From: Sander Roet Date: Thu, 29 Feb 2024 14:51:08 +0100 Subject: [PATCH 13/14] catch all errors instead --- tests/test_broken_imports.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_broken_imports.py b/tests/test_broken_imports.py index 48f00e93..dc7c1854 100644 --- a/tests/test_broken_imports.py +++ b/tests/test_broken_imports.py @@ -8,7 +8,7 @@ SKIP_PLOT = False try: import pytom_tm.plotting -except ModuleNotFoundError: +except: SKIP_PLOT = True def module_not_found_mock(missing_name): From d9926eb03d17fcfb41bb2cad36cd5a61cf61f454 Mon Sep 17 00:00:00 2001 From: Sander Roet Date: Thu, 29 Feb 2024 15:24:05 +0100 Subject: [PATCH 14/14] update coverage to 79 (currently at 80) --- .github/workflows/coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index e2570637..2e693b4e 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -44,7 +44,7 @@ jobs: path: coverage.xml repo_token: ${{ secrets.GITHUB_TOKEN }} pull_request_number: ${{ steps.get-pr.outputs.PR }} - minimum_coverage: 78 + minimum_coverage: 79 show_missing: True fail_below_threshold: True link_missing_lines: True