Skip to content

Commit

Permalink
add tests for missing libraries (#127)
Browse files Browse the repository at this point in the history
* add tests for missing libraries

* also add the test file

* fix some typo's

* actually go for logging instead of raising a warning

* try using importlib reload instead

* make sure mocks are working

* try overriding namespace as well

* see if reloading the full module works

* also do reload on to see if the tests fail

* remove extra_filter and mock matplotlib.pyplot instead

* move mock definitions to inside the test

* restructure plotting import to be testable

* update minimum coverage to 78 to reflect updated score (79)

* Update src/pytom_tm/__init__.py

Co-authored-by: Marten <[email protected]>

* remove unnesesary base matplotlib import

---------

Co-authored-by: Marten <[email protected]>
  • Loading branch information
sroet and McHaillet authored Feb 28, 2024
1 parent de1141e commit 0bd4763
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 7 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
path: coverage.xml
repo_token: ${{ secrets.GITHUB_TOKEN }}
pull_request_number: ${{ steps.get-pr.outputs.PR }}
minimum_coverage: 75
minimum_coverage: 78
show_missing: True
fail_below_threshold: True
link_missing_lines: True
Expand Down
4 changes: 3 additions & 1 deletion src/pytom_tm/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import logging
from importlib import metadata
__version__ = metadata.version('pytom-match-pick')


try:
import cupy
except (ModuleNotFoundError, ImportError):
print('Error for template matching: cupy installation not found or not functional.')
logging.warning('Error for template matching: cupy installation not found or not functional.')
1 change: 0 additions & 1 deletion src/pytom_tm/extract.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

plotting_available = False
try:
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(context='talk', style='ticks')
Expand Down
8 changes: 4 additions & 4 deletions src/pytom_tm/plotting.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
from scipy.optimize import curve_fit
from scipy.special import erf

if find_spec("matplotlib") is None or find_spec("seaborn") is None:
try:
import matplotlib.pyplot as plt
import seaborn as sns
except ModuleNotFoundError:
raise RuntimeError(
"ROC estimation can only be done when matplotlib and seaborn are installed."
)
else:
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(context="talk", style="ticks")


Expand Down
85 changes: 85 additions & 0 deletions tests/test_broken_imports.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# No imports of pytom_tm outside of the methods
import unittest
from importlib import reload
# Mock out installed dependencies
orig_import = __import__

def module_not_found_mock(missing_name):
def import_mock(name, *args):
if name == missing_name:
raise ModuleNotFoundError(f"No module named '{name}'")
return orig_import(name, *args)
return import_mock

def cupy_import_error_mock(name, *args):
if name == 'cupy':
raise ImportError("Failed to import cupy")
return orig_import(name, *args)


class TestMissingDependencies(unittest.TestCase):

def test_missing_cupy(self):
# assert working import
with self.assertNoLogs(level='WARNING'):
import pytom_tm
cupy_not_found = module_not_found_mock('cupy')
# Test missing cupy
with unittest.mock.patch('builtins.__import__', side_effect=cupy_not_found):
with self.assertLogs(level='WARNING') as cm:
reload(pytom_tm)
self.assertEqual(len(cm.output), 1)
self.assertIn("cupy installation not found or not functional", cm.output[0])

def test_broken_cupy(self):
# assert working import
with self.assertNoLogs(level='WARNING'):
import pytom_tm
# Test cupy ImportError
with unittest.mock.patch('builtins.__import__', side_effect=cupy_import_error_mock):
with self.assertLogs(level='WARNING') as cm:
reload(pytom_tm)
self.assertEqual(len(cm.output), 1)
self.assertIn("cupy installation not found or not functional", cm.output[0])

def test_missing_matplotlib(self):
# assert working import
import pytom_tm

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'):
# only pyplot is directly imported so this should be tested
import matplotlib.pyplot as plt
# force reload
# check if we can still import pytom_tm
reload(pytom_tm)

# check if plotting is indeed disabled after reload
# (reload is needed to prevent python import caching)
self.assertFalse(reload(pytom_tm.template).plotting_available)
self.assertFalse(reload(pytom_tm.extract).plotting_available)
# assert that importing the plotting module fails completely
with self.assertRaisesRegex(RuntimeError, "matplotlib and seaborn"):
reload(pytom_tm.plotting)

def test_missing_seaborn(self):
# assert working import
import pytom_tm

seaborn_not_found = module_not_found_mock('seaborn')
with unittest.mock.patch('builtins.__import__', side_effect=seaborn_not_found):
with self.assertRaisesRegex(ModuleNotFoundError, 'seaborn'):
import seaborn
# check if we can still import pytom_tm
reload(pytom_tm)
# check if plotting is indeed disabled
# (reload is needed to prevent python import caching)
self.assertFalse(reload(pytom_tm.template).plotting_available)
self.assertFalse(reload(pytom_tm.extract).plotting_available)
# assert that importing the plotting module fails completely
with self.assertRaisesRegex(RuntimeError, "matplotlib and seaborn"):
reload(pytom_tm.plotting)



0 comments on commit 0bd4763

Please sign in to comment.