Pytest.importorskip skips tests where module not found

1 minute read

Pytest allows clean handling of numerous continuous integration challenges. Many programs use advanced plotting that may not be desired to test on continuous integration. For example, one might opt not to install matplotlib as part of CI runs. We put plotting routines in a separate file to facilitate this, allowing the core module functions to have a bare minimum set of prereqs. This is useful for HPC, CI and cloud scenarios that either may not plot locally or that may use varied plotting systems depending on whether running on web or local PC.

pytest.importorskip() is a vital tool to handle to cleanly and clearly handle these scenarios.

Example

Imagine a Python package file hierarchy like:

setup.py
setup.cfg
RunMyprog.py

mymod/
    __init__.py
    plot.py
    funcs.py
    adv.py
    tests/
        test_mod.py
        test_scripts.py
        test_plots.py

Suppose optional module mymod.adv() requires scikit-image, which itself has a lot of prereqs. One might opt to have CI not install scikit-image, and then use pytest.importorskip() to cleanly skip complicated, optional tests on CI, HPC etc.

test_mod.py contains:

import pytest
import mymod


def test_base():
    ...
    

def test_advanced():

    adv = pytest.importorskip('mymod.adv')
    
    ...

The pytest.importorskip is equivalent to

import mymod.adv as adv

if available, or

pytest.skip()

if not available.

This is very clean and more importantly clear way to handle complex optional prereqs for CI on various platforms.

Conditional skipping

The functionality above can be generalized to handle more complicated cases, or even become a decorator with pytest.skipif.

import pytest
import os

@pytest.mark.skipif(os.name=='nt', reason='only for Unix-like systems')
def test_unix():
    ...

If you have more than one function to skip with the same test skip condition, make your own decorator:

import pytest
import os

unixonly = pytest.mark.skipif(os.name=='nt', reason='only for Unix-like systems')


@unixonly
def test_unix_plot():
    ...
   
   
@unixonly
def test_unix_network():
    ...

Leave a comment