When testing Python code, one sometimes has to imitate a broken or missing module. In a specific example, the pywin32
package requires running a post-installation script with administrator privileges after initial installation. Importing, for example, the win32security
module of pywin32
may throw an ImportError
if the postinstallation script wasn't executed. Packages that depend on pywin32
may want to handle this situation gracefully so that users who just pip install mypackage
get only a soft failure or at least a helpful error message. If one wants to test this behavior in continuous integration and get code coverage, the ImportError
has to be triggered even if pywin32
is installed correctly. Here is a short example that mimicks a broken or missing package with pytest
and monkeypatch
, since I didn't find this elsewhere:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | import sys
import builtins
import pytest
real_import = builtins.__import__
def monkey_import_notfound(name, globals=None, locals=None, fromlist=(), level=0):
if name in ('win32security', 'pywintypes'):
raise ModuleNotFoundError(f"Mocked module not found {name}")
return real_import(name, globals=globals, locals=locals, fromlist=fromlist, level=level)
def monkey_import_importerror(name, globals=None, locals=None, fromlist=(), level=0):
if name in ('win32security', ):
raise ImportError(f"Mocked import error {name}")
return real_import(name, globals=globals, locals=locals, fromlist=fromlist, level=level)
def test_import_selftest(monkeypatch):
monkeypatch.delitem(sys.modules, 'win32security', raising=False)
monkeypatch.setattr(builtins, '__import__', monkey_import_importerror)
with pytest.raises(ImportError):
import win32security
def test_import_selftest2(monkeypatch):
monkeypatch.delitem(sys.modules, 'win32security', raising=False)
monkeypatch.setattr(builtins, '__import__', monkey_import_notfound)
with pytest.raises(ModuleNotFoundError):
import win32security
def test_import_broken(monkeypatch):
monkeypatch.delitem(sys.modules, 'win32security', raising=False)
monkeypatch.delitem(sys.modules, 'my_module_using_win32security', raising=False)
monkeypatch.setattr(builtins, '__import__', monkey_import_importerror)
# Example: handle error with a fallback function with reduced capabilities
from my_module_using_win32security import my_function, my_graceful_fallback
assert my_function is my_graceful_fallback
def test_import_missing(monkeypatch):
monkeypatch.delitem(sys.modules, 'win32security', raising=False)
monkeypatch.delitem(sys.modules, 'my_module_using_win32security', raising=False)
monkeypatch.setattr(builtins, '__import__', monkey_import_notfound)
# Example: handle missing module with a fallback function with reduced capabilities
from my_module_using_win32security import my_function, my_graceful_fallback
assert my_function is my_graceful_fallback
|
Comments
No comments yet.