Skip to content
tezvyn:
Menu

Run One Test with Many Inputs using pytest.parametrize

Source: docs.pytest.orgMediumHow cards are made

Run one test function with many inputs using @pytest.mark.parametrize, avoiding repetitive code. It's ideal for checking a function against various inputs, edge cases, and expected failures. The footgun: mutable parameters like lists are passed by reference.

Why it exists

Testing a function often requires checking it against many different inputs. Writing a separate test function for each input leads to a lot of boilerplate code, making the test suite hard to read and maintain. Parameterization was created to solve this by running the same test logic with different data.

The mental model

Think of @pytest.mark.parametrize as a for loop that runs on top of your test function. You define a list of data sets (the inputs and expected outputs), and pytest executes your test once for each set, injecting the data as arguments. This keeps your test logic DRY (Don't Repeat Yourself) and your data separate from your test implementation.

How it works

You apply the @pytest.mark.parametrize decorator directly above a test function. The decorator takes two primary arguments: first, a string containing comma-separated names for the arguments your test function will receive, and second, a list of tuples. Each tuple represents one complete set of arguments for a single test run. Pytest generates a unique test for each tuple, making it easy to see which specific data set caused a failure. A key detail: if you pass a mutable object like a list or dict, it is passed by reference. Any modification inside the test will persist for subsequent runs using that same object, which can lead to confusing, order-dependent failures.

When to use it

Parameterization is ideal for data-driven testing. Use it when you need to verify a function's behavior across a range of inputs. This includes testing multiple valid inputs, boundary conditions (like empty lists, zero, or null values), and different inputs that should all produce the same expected outcome.

When not to use it

If the test logic itself needs to change significantly for different inputs, separate test functions are clearer. For very complex or dynamic test generation scenarios, especially those that depend on configuration or other fixtures, the pytest_generate_tests hook provides more advanced control than this decorator.

One canonical example

Consider a test for Python's eval function.

import pytest

@pytest.mark.parametrize("test_input,expected", [("3+5", 8), ("2+4", 6), ("6*9", 42)])

def test_eval(test_input, expected):

assert eval(test_input) == expected This will run test_eval three times. The first two runs will pass. The third run will fail because eval("69") is 54, not 42. Pytest will report this specific failure as test_eval[69-42], clearly showing the input values that caused the test to fail while allowing the other cases to pass.

Interview question

Which of the following describes a critical "footgun" when using @pytest.mark.parametrize with mutable objects like lists?

  • a.Modifications made to a mutable object in one parameterized test run will persist and affect subsequent runs using that same object.Correct
  • b.Parameterized tests cannot effectively handle mutable objects, requiring separate test functions instead.
  • c.The test function will automatically deep copy mutable objects, increasing memory usage.
  • d.Pytest will raise an error if a mutable object is not explicitly reset to its original state before each test execution.
Why?

The card states that mutable objects are passed by reference, meaning any modification in one test run will persist and affect subsequent runs using the same object. Pytest does not automatically deep copy or enforce resetting, which is precisely why this is a 'footgun'.

Just read this? Test yourself on what you have been reading.

Read the original → docs.pytest.org

Put your scrolling time to good use

Learn one idea, try a quiz and save useful cards for revision. Tezvyn makes it easy to learn and stay current in your tech field, a few minutes at a time.

The iPhone app is on the way

We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.

Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.

Get it on Google PlayiPhone app coming soon

We are hiring for this. Open roles that interview on python — each one lists the topics its interview covers.

See open roles