Skip to content Skip to sidebar Skip to footer

How To Write Unittests For An Optional Dependency In A Python Package?

Based on availability of pandas package in working environment a method returns two different outputs : A pandas.DataFrame if pandas is available Otherwise a numpy.recarray object

Solution 1:

If you want to test both cases (which you should), you could possibly force the import of Pandas to fail by adding None to the 'pandas' entry in sys.modules, making sure to add it back again (or delete the entry if it didn't exist in the first place) once the test is done.

import unittest
import sys

classTestWithoutPandas(unittest.TestCase):
    defsetUp(self):
        self._temp_pandas = Noneif sys.modules.get('pandas'):
            self._temp_pandas = sys.modules['pandas']
        sys.modules['pandas'] = NonedeftearDown(self):
        if self._temp_pandas:
            sys.modules['pandas'] = self._temp_pandas
        else:
            del sys.modules['pandas']

    deftests_using_pandas(self):
        flag = Falsetry:
            import pandas
        except ImportError:
            flag = True
        self.assertTrue(flag)

classTestWithPandas(unittest.TestCase):
    deftests_using_pandas(self):
        flag = Falsetry:
            import pandas
        except ImportError:
            flag = True
        self.assertFalse(flag)

Solution 2:

IMHO, you should alway run the tests not requiring PANDAS, because nothing prevents you to.

But you should indeed skip the requiring pandas if pandas is not present at test time, because you would get uninformative errors simply caused by the absence of an optional component.

That way, when you test on your own environment (with pandas I assume), you will test both cases, but if another user wants to run the tests in an environment without pandas, it can still test the part he will use.

So my advice would be:

@unittest.skipUnless(HAVE_PANDAS, "requires pandas")
deftests_using_pandas(self):
    # do somethingdeftests_without_pandas(self):
    # do something

Solution 3:

import sys
from unittest.mock import patch

deftest_without_panda(self):
    with patch.dict(sys.modules, {'pandas': None}):
        # do whatever you want

What the above code does is, it mocks that the package panda is not installed and runs your test in that isolated environment inside the context-manager(with).

Keep in mind, you might have to reload the module under test depending upon your use case

import sys
from unittest.mock import patch
from importlib import reload

deftest_without_panda(self):
    with patch.dict(sys.modules, {'pandas': None}):
        reload(sys.modules['my_module_under_test'])
        # do whatever you want

Post a Comment for "How To Write Unittests For An Optional Dependency In A Python Package?"