diff --git a/pygmt/helpers/testing.py b/pygmt/helpers/testing.py index 9b20312e416..9cc88f1076a 100644 --- a/pygmt/helpers/testing.py +++ b/pygmt/helpers/testing.py @@ -1,10 +1,12 @@ """ Helper functions for testing. """ +import importlib import inspect import os import string +import pytest from pygmt.exceptions import GMTImageComparisonFailure from pygmt.io import load_dataarray from pygmt.src import which @@ -237,3 +239,42 @@ def load_static_earth_relief(): """ fname = which("@static_earth_relief.nc", download="c") return load_dataarray(fname) + + +def skip_if_no(package): + """ + Generic function to help skip tests when required packages are not present + on the testing system. + + This function returns a pytest mark with a skip condition that will be + evaluated during test collection. An attempt will be made to import the + specified ``package``. + + The mark can be used as either a decorator for a test class or to be + applied to parameters in pytest.mark.parametrize calls or parametrized + fixtures. Use pytest.importorskip if an imported moduled is later needed + or for test functions. + + If the import is unsuccessful, then the test function (or test case when + used in conjunction with parametrization) will be skipped. + + Adapted from + https://github.com/pandas-dev/pandas/blob/v2.1.4/pandas/util/_test_decorators.py#L121 + + Parameters + ---------- + package : str + The name of the required package. + + Returns + ------- + pytest.MarkDecorator + A pytest.mark.skipif to use as either a test decorator or a + parametrization mark. + """ + try: + _ = importlib.import_module(name=package) + has_package = True + except ImportError: + has_package = False + return pytest.mark.skipif(not has_package, reason=f"Could not import '{package}'") diff --git a/pygmt/tests/test_helpers.py b/pygmt/tests/test_helpers.py index b726897e12e..78f56617054 100644 --- a/pygmt/tests/test_helpers.py +++ b/pygmt/tests/test_helpers.py @@ -15,7 +15,7 @@ kwargs_to_strings, unique_name, ) -from pygmt.helpers.testing import load_static_earth_relief +from pygmt.helpers.testing import load_static_earth_relief, skip_if_no def test_load_static_earth_relief(): @@ -147,3 +147,19 @@ def test_args_in_kwargs(): # Failing list of arguments failing_args = ["D", "E", "F"] assert not args_in_kwargs(args=failing_args, kwargs=kwargs) + + +def test_skip_if_no(): + """ + Test that the skip_if_no helper testing function returns a + pytest.mask.skipif mark decorator. + """ + # Check pytest.mark with a dependency that can be imported + mark_decorator = skip_if_no(package="numpy") + assert mark_decorator.args[0] is False + + # Check pytest.mark with a dependency that cannot be imported + mark_decorator = skip_if_no(package="nullpackage") + assert mark_decorator.args[0] is True + assert mark_decorator.kwargs["reason"] == "Could not import 'nullpackage'" + assert mark_decorator.markname == "skipif"