In the hips package, often data has to be fetched from remote servers, especially HiPS tiles. One way to cut back on the queries was by introducing the hips-extra repository. This contains HiPS tiles from various HiPS surveys. This allows us to quickly fetch tiles from local storage, which makes the testing process less time-consuming.
In Python, the path can be retrieved using the
os.environ['HIPS_EXTRA']. Now, what if the user does not have hips-extra repository on their system. In this case, we don’t want to raise any errors, but to simply skip the test case. In order to do this, Python decorators become useful.
A brief overview on Python Decorators
Decorators provide a simple syntax for calling higher-order functions. By definition, a decorator is a function that takes another function and extends the behavior of the latter function without explicitly modifying it. Some of the most commonly used decorators are
@property, etc. The decorators are written above a function header, like this:
@property def name(self): return self.name
Writing your own decorators
To write our decorators, we create a wrapper function around
pytest.mark.skipif. The documentation of this function can be viewed to get detailed information on how it works. The function below checks if the
HIPS_EXTRA environment variable is set on the user’s system, and if it is, it returns a True boolean .
import os from pathlib import Path def has_hips_extra(): """Is hips-extra available? (`bool`)""" if 'HIPS_EXTRA' in os.environ: path = Path(os.environ['HIPS_EXTRA']) / 'datasets/samples/DSS2Red/properties' if path.is_file(): return True return False
A separate function below makes use of the above function to check whether the package is available or not:
import pytest def requires_hips_extra(): """Decorator to mark tests requiring ``hips-extra`` data.""" skip_it = not has_hips_extra() reason = 'No hips-extra data available.' return pytest.mark.skipif(skip_it, reason=reason)
This decorator can now be used. An example illustrating its use is shown below. First we import the function from its location and then apply it to another function that uses data from hips-extra repository:
from hips.utils.testing import requires_hips_extra @requires_hips_extra() def test_draw_sky_image(): ...
If the user’s
HIPS_EXTRA environment variable does not have a valid path, the above test will be skipped.