Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making a Python test think an installed package is not available

Tags:

python

pytest

I have a test that makes sure a specific (helpful) error message is raised, when a required package is not available.

def foo(caller):
    try:
        import pkg
    except ImportError:
        raise ImportError(f'Install "pkg" to use {caller}')
    pkg.bar()

with pytest.raises(ImportError, match='Install "pkg" to use test_function'):
   foo('test_function')

However, pkg is generally available, as other tests rely on it. Currently, I set up an additional virtual env without pkg just for this test. This seems like overkill.

Is it possible to "hide" an installed package within a module or function?

like image 577
rvf Avatar asked Feb 14 '20 13:02

rvf


People also ask

Why can't Python find my module?

This is caused by the fact that the version of Python you're running your script with is not configured to search for modules where you've installed them. This happens when you use the wrong installation of pip to install packages.

Where is my Python module installed?

For most Linux environments, Python is installed under /usr/local , and the libraries can be found there. For Mac OS, the home directory is under /Library/Frameworks/Python. framework . PYTHONPATH is used to add directories to the path.

How do I see what packages are installed in Anaconda?

Start the Anaconda Navigator application. Select Environments in the left column. A dropdown box at the center-top of the GUI should list installed packages. If not, then select Installed in the dropdown menu to list all packages.


2 Answers

I ended up with the following pytest-only solution, which appears to be more robust in the setting of a larger project.

import builtins
import pytest


@pytest.fixture
def hide_available_pkg(monkeypatch):
    import_orig = builtins.__import__

    def mocked_import(name, *args, **kwargs):
        if name == 'pkg':
            raise ImportError()
        return import_orig(name, *args, **kwargs)

    monkeypatch.setattr(builtins, '__import__', mocked_import)


@pytest.mark.usefixtures('hide_available_pkg')
def test_message():
    with pytest.raises(ImportError, match='Install "pkg" to use test_function'):
        foo('test_function')
like image 168
rvf Avatar answered Oct 23 '22 23:10

rvf


You can mock builtins.__import__.

from unittest import mock

import pytest


def foo(caller):
    try:
        import pkg
    except ImportError:
        raise ImportError(f'Install "pkg" to use {caller}')
    pkg.bar()

with mock.patch("builtins.__import__", side_effect=ImportError):
    with pytest.raises(ImportError, match='Install "pkg" to use test_function'):
        foo('test_function')
like image 44
Łukasz Rogalski Avatar answered Oct 23 '22 23:10

Łukasz Rogalski