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 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..4dc3293a 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 = true 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): diff --git a/tests/test_broken_imports.py b/tests/test_broken_imports.py index a4fca053..dc7c1854 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: + 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 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'): 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))