Getting started

Rationale

Parametrizing your tests—in other words, separating the test data from the test code—is frequently a good idea. It makes it easier to add new test cases, while also making it easier to read and understand the test code.

Parametrize From File provides a convenient way to parametrize tests when using the popular pytest framework. The central idea is to keep the parameters in their own files, separate from the test code. This prevents long lists of parameters from dwarfing your test code, and often allows parameters to be specified more clearly and succinctly than would be possible in python.

Installation

Install Parametrize From File using pip:

$ pip install parametrize_from_file

Writing the parameters

In this tutorial, we’ll write some tests for a dot product function meant to work with a simple 2D vector class:

vector.py
class Vector:

    def __init__(self, x, y):
        self.x = x
        self.y = y

def dot(a, b):
    return a.x * b.x + a.y * b.y

We’ll specify the parameters for the tests in their own file. This file can be JSON, YAML, TOML, or NestedText. We’ll use YAML for this example, since it’s simple and well-known, but I’ll note that NestedText is generally a better choice for real tests (for the reasons discussed here).

test_vector.yml
test_dot:
  -
    a: [0, 0]
    b: [1, 2]
    expected: 0
  -
    a: [1, 0]
    b: [1, 2]
    expected: 1
  -
    a: [0, 1]
    b: [1, 2]
    expected: 2
  -
    a: [1, 1]
    b: [1, 2]
    expected: 3

Note that the parameters are indexed by test function (test_dot in this case). This allows parameters for multiple test functions to be specified in a single file. The usual organization is to have one parameter file per test file, with both files having the same base name and containing the same set of tests.

Writing the tests

Write the test function as if you were using pytest.mark.parametrize. The function should accept an argument for each parameter, and the name of the argument should match the name of the parameter in the file. Decorate the test function directly with the parametrize_from_file module.

test_vector.py
import parametrize_from_file
from vector import Vector, dot
from pytest import approx

@parametrize_from_file
def test_dot(a, b, expected):
    a, b = Vector(*a), Vector(*b)
    assert dot(a, b) == approx(expected)

Running the tests

Run the tests using pytest, in the same way you normally would. Note that all four tests are run:

$ pytest test_vector.py
============================= test session starts ==============================
platform linux -- Python 3.8.2, pytest-6.1.2, py-1.9.0, pluggy-0.13.1
rootdir: /home/kale/hacking/projects/parametrize_from_file, configfile: pyproject.toml
plugins: forked-1.1.3, cov-2.8.1, xonsh-0.9.24, xdist-1.32.0, hypothesis-5.8.3, mock-2.0.0
collected 4 items

test_vector.py ....                                                      [100%]

============================== 4 passed in 0.15s ===============================