3

I have a package that has an optional library install. When the optional library is not present and the particular method is called a custom exception is raised saying the feature is not enabled without the optional package install. When the optional library is present then the method can be used.

I want to test both of these cases with pytest.

I am importing the libraries like:

try:
    import derp
except ImportError:
    pass

And then in the function checking if the library is installed by checking if the package is in sys.modules.

def my_feature_method():
    if 'derp' not in sys.modules:
        raise Exception('this feature requires the derp package to be installed')

    # do some stuff ...

I want to be able to test the case where the package is installed and is not installed in pytest.

Edit

At the moment I am using

with mock.patch.dict('sys.modules'):
    del sys.modules['derp']
    # run test

But this doesn't actually test that the ImportError is raised. I want this for coverage reasons

Ross MacArthur
  • 4,735
  • 1
  • 24
  • 36

2 Answers2

1

Okay I solved this by changing my setup a bit:

def try_import(name, package=None):
    try:
        return importlib.import_module(name, package=package)
    except ImportError:
        pass

derp = try_import('derp')

if not globals()['derp']:
    raise Exception('this feature requires the derp package to be installed')

This means two things:

  1. I can test the try_import function seperately.

  2. I can simply patch the name like mock.patch('__main__.derp', None)

Ross MacArthur
  • 4,735
  • 1
  • 24
  • 36
0

You could mock the sys.path to prevent import finding your the library. Something like

import unittest.mock
import sys
with unittest.mock.patch('sys.path', []):
    try:
        import derp
    except ImportError:
        pass
    if 'derp' not in sys.modules:
        raise Exception('missing derp')
user590028
  • 11,364
  • 3
  • 40
  • 57