parametrize_from_file.parametrize

parametrize_from_file.parametrize(path=None, key=None, *, loaders=None, preprocess=None, schema=None, **kwargs)

Parametrize a test function with values read from a config file.

Parameters:
  • path (str,pathlib.Path,list) –

    The path to the parameter file, relative to the directory containing the test file. By default, the parameter file will be assumed to have the same base name as the test file and one of the extensions listed in the file format table below.

    If multiple paths are specified, the parameters from each will be loaded and concatenated. The key argument in this case must be either be a string (meaning: lookup the same key in each file) or a list of strings with the same length as this argument (meaning: look up the corresponding key in each file).

  • key (str,list) –

    The key that will be used to identify the parameters affiliated with the decorated test function. The default is to use the name of the test function. See below for more detail about the structure of the parameters file.

    If multiple keys are specified, the parameters for each will loaded and concatenated. The path argument in this case must be either a single path (meaning: lookup all keys in the same file) or a list of paths with the same length as this argument (meaning: look up each key in the corresponding file).

  • loaders (dict) – A dictionary mapping file extensions (e.g. '.nt') to functions that load test parameters from files (e.g. nestedtext.load). See add_loader for a more complete description of these functions. The items in this dictionary override the globally defined loaders for the purposes of the decorated test function.

  • preprocess (collections.abc.Callable) –

    A function that will be allowed to modify the list of test cases loaded from the parameter file, e.g. to programmatically generate and/or prune test cases. The function should have the following signature:

    def preprocess(params: Any, [context: Context]) -> List[Dict[str, Any]]
    

    The first argument will be the value associated with the given key in the parameter file. Typically this value is a list, but it could be anything. If the function accepts a second argument (which it doesn’t have to), it will be an object with path and key attributes specifying where the aforementioned value was loaded from. If multiple parameter files and/or keys are specified, this function will be called separately on each one. The return value must be a list of dicts. Each of these dicts will be further processed by the schema argument before being used to parametrize the test function. Note that this function does get access to the special id and marks fields, unlike the schema function.

  • schema (collections.abc.Callable,list) –

    One or more functions that will be used to validate and/or transform each set of parameters. Each function should have the following signature:

    def schema(params: Dict[str: Any]) -> Dict[str, Any]:
    

    The argument will be the set of parameters for a single test case, excluding the special id and marks fields. The return value will be used to actually parametrize the test function. It’s ok to add or remove keys from the input dictionary, but keep in mind that every set of parameters for a single test function must ultimately have the same keys (which must match the argument list for that function).

    The schema may also set the id and marks fields. If an ID is specified in the file, it will override the one set by the schema. If any marks are specified in the file, they will be added to those specified by the schema. The schema can either set marks in the same way as the file (i.e. as a string or list of strings), or as a list of actual pytest.mark objects.

    If multiple functions are specified, each will be applied in the order given. The output from one function will be the input to the next. You can think of these functions as forming a pipeline.

    While it’s possible to write your own schema functions, this argument is most often used in conjunction with defaults, cast, error_or, or a third-party data validation library such as voluptuous or schema.

  • kwargs – Any other keyword arguments are passed on directly to pytest.mark.parametrize.

The parameter file must be in one of the following formats, and must have a corresponding file extension:

Format

Extensions

JSON

.json

YAML

.yml .yaml

TOML

.toml

NestedText

.nt

The top-level data structure in the parameter file should be a dictionary. The keys of this dictionary should be the names of the individual tests, and the values should be lists of parameter sets to provide to that test. Each parameter set should be a dictionary, with the keys being the names of the parameters and the values being the parameters themselves. Each parameter set within a list must have the same set of keys (except for the specially-treated id and marks keys, described below). There are no restrictions on the values of the parameters (e.g. different parameter sets within the same list can have values of different types).

For example, here is a valid YAML parameter file. This file specifies two sets of parameters for each of two tests:

test_addition:
  - operands: [0, 0]
    expected: 0

  - operands: [0, 1]
    expected: 1

test_subtraction:
  - operands: [0, 0]
    expected: 0

  - operands: [0, 1]
    expected: -1

There are two parameter names that are treated specially:

Parameters:
  • id (str) – A name that will be used by pytest to refer to this particular set of parameters, e.g. if they cause a test failure. If not given, the parameter set will be assigned a numeric id that counts up from 1. It’s ok for multiple test cases to have the same id; pytest will distinguish them by appending a numeric id that counts up from 0.

  • marks (str,list) – One or more marks (like skip or xfail) that should be applied this particular set of parameters. If a plain string is given, it will be split on commas. If a list is given, each element should be a string. Pytest will issue a warning if you use a mark that it doesn’t recognize.

This decorator can be used with or without arguments, and the parametrize_from_file module itself can be used directly as a decorator. The decorated function should accept arguments with the same names as each of its parameters specified in the file. It is possible to decorate the same test function multiple times: all combinations of parameters specified in this way will be tested. Likewise, this decorator can be combined freely with the pytest.mark.parametrize decorator.

The resulting decorated test function will have attributes corresponding to the path, key, loaders, preprocess, and schema arguments. These attributes are sometimes useful for sharing the same parameters between multiple tests.

Example

Load parameters from a NestedText file, and assign types using a schema:

# test_utils.nt
test_is_even:
  -
    value: 1
    expected: False
  -
    value: 2
    expected: True
# test_utils.py
import parametrize_from_file
from parametrize_from_file import cast

def is_even(x):
    return x % 2 == 0

@parametrize_from_file(schema=cast(value=int, expected=eval))
def test_is_even(value, expected):
    assert is_even(value) == expected