run_test

plasmapy.utils.pytest_helpers.run_test(func, args: Any = (), kwargs: Dict = {}, expected_outcome: Any = None, rtol: float = 0.0, atol: float = 0.0)

Test that a function or class returns the expected result, raises the expected exception, or issues an expected warning for the supplied positional and keyword arguments.

Parameters:
  • func (callable, list, or tuple) – The callable to be tested. The first (and sole) argument to run_test may alternatively be a list or tuple containing these arguments (optionally omitting kwargs if the len returns 3).
  • args (tuple or object) – The positional arguments to func.
  • kwargs (dict) – The keyword arguments to func.
  • expected_outcome (object) – The expected result, exception, or warning from func(*args, **kwargs). This may also be a tuple of length two that contains the expected result as the first item and the expected warning as the second item.
  • rtol (float) – The relative tolerance to be used by allclose in an element-wise comparison, defaulting to 0.
  • atol (float) – The absolute tolerance to be used by allclose in an element-wise comparison, defaulting to 0.
Returns:

Return type:

None

Raises:
  • UnexpectedResultError – If the test returns a result that is different from the expected result.
  • InconsistentTypeError – If the actual result is of a different type than the expected result.
  • UnexpectedExceptionError – If an exception occurs when no exception or a different exception is expected.
  • MissingExceptionError – If no exception is raised when an exception is expected.
  • MissingWarningError – An expected warning is not issued.
  • UnitsError – If the result has different units than expected.
  • TypeError – If the equality of the actual result and expected result cannot be determined (e.g., for a class lacking an __eq__ method.

Examples

The simplest way to use run_test is with inputs for the function to be tests, the positional arguments in a tuple or list, the keyword arguments in a dict, and then finally the expected result or outcome.

>>> args = tuple()
>>> kwargs = dict()
>>> run_test(lambda: 0, args, kwargs, 0)

If expected is a an exception or warning, then run_test will raise an exception if the expected exception is not raised or the expected warning is not issued.

>>> from warnings import warn
>>> issue_warning = lambda: warn("Electrons are weird!", UserWarning)
>>> run_test(issue_warning, args, kwargs, UserWarning)
>>> def raise_exception(): raise RuntimeError
>>> run_test(raise_exception, args, kwargs, RuntimeError)

For warnings, run_test can accept a tuple of two items where the first item is the expected result and the second item is the expected warning.

def return_arg_and_warn(x):
    warn("", UserWarning)
    return x

run_test(return_arg_and_warn, 1, {}, (1, UserWarning))

This function is also flexible enough that it can accept a tuple or list as its sole argument, with the arguments in the same order as in the function signature.

>>> return_arg = lambda x: x
>>> inputs = (return_arg, 42, {}, 42)
>>> run_test(inputs)

If the tuple or list has a length of 3, then run_test assumes that kwargs is missing.

>>> inputs_without_kwargs = [return_arg, 42, 42]
>>> run_test(inputs_without_kwargs)
import pytest

def func(x, raise_exception=False, issue_warning=False):
    if raise_exception:
        raise ValueError("I'm sorry, Dave. I'm afraid I can't do that.")
    elif issue_warning:
        warn("Open the pod bay doors, HAL.", UserWarning)
    return x

inputs_table = [
    (func, 1, 1),
    (func, (2,), {}, 2),
    (func, 3, {'raise_exception': True}, ValueError),
    (func, 4, {'issue_warning': True}, UserWarning),
    (func, 5, {'issue_warning': True}, (5, UserWarning)),
]

@pytest.mark.parametrize('inputs', inputs_table)
def test_func(inputs):
    run_test(inputs)