Kurt Bourbaki
Kurt Bourbaki

Reputation: 12606

Test warnings for optional packages

My code provides optional functionalities that use optional packages.

When a user imports a package which contains these optional features, a warning is displayed if he/she does not have the additional package installed. E.g.:

Please install optional-package to use all features

In order to test these optional features, the optional package is installed as a dependency in the virtualenv that tox creates:

# tox.ini
[my-env]
deps = optional-package

The problem is that I want to test that:

  1. A warning is displayed when the user does not have the package installed
  2. The warning is not displayed when the user does have the package

However, it seems that python does not provide a way to unload packages.

How can I create a test to describe the context in which the user does not have the optional package on his system, if at the same time I need tox to automatically install it as a dependency?

Upvotes: 1

Views: 248

Answers (1)

Sven Marnach
Sven Marnach

Reputation: 602115

Here is one way to test that some_module throws a warning when optional.package is not available:

import some_module

# ...

    @mock.patch.dict("sys.modules", {"optional.package": None})
    def test_warning_optional_package_not_installed(self):
        with self.assertWarns(SomeWarning):
            imp.reload(some_module)

Alternatively, you can define multiple testing environments in your tox.ini file, with and without the optional packages. You can configure tox to set environment variables depending on whether the package has been installed:

[tox]
envlist = {with,without}_optional

[testenv]
basepython = python3.5
deps =
    required-package
    with_optional: optional-package
setenv = 
    with_optional: OPTIONAL_PACKAGE_AVAILABLE = true
commands = python -m unittest tests

You can then enable and disable tests based on the value of the environment variable:

@unittest.skipUnless(os.env["OPTIONAL_PACKAGE_AVAILABLE"] == "true")
def test_no_warning_optional_package(self):
    with warnings.catch_warnings(record=True) as w:
        imp.reload(some_module)
    self.assertFalse(w)

Upvotes: 1

Related Questions