Skip to main content

One Test, Many Cases

Most functions need the same check for many inputs: normal values, negative values, zero, edge cases. Copying the test five times makes five places to maintain.

The answer is a table-driven test: put the cases into a list of tuples — each case holds a name, the inputs and the expected output — and run the same check over all of them.

Adding a new case becomes one new line in the table. This is one of the most common test patterns you will see in real code.


The Table

The simplest table is a list of tuples right inside the test. Each entry is one case: a name (for the failure message), the inputs, and the expected result.

The loop calls the function once per case and compares the result. The first mismatch would stop the test at that case, and the message carries the case name — that is how you know which row broke.

Four cases in one table

Four cases, one loop, one check. All pass here, so the run shows a single passing test. To test a fifth situation you would add one line to the table — the loop stays untouched.

Prompt
Write a Python table-driven test for an add function: a list of tuples with a case name, two inputs and the expected result, covering one plus one, positive and negative, both negative, and zeros. Loop over the table and assert each case with a message that includes the case name. Show the pytest -v output.
Output: complete Python program
Four cases in one table

One Test per Case with parametrize

pytest can turn each table row into its own test: the @pytest.mark.parametrize decorator takes the argument names and the list of cases, and calls the test function once per row.

The ids list gives each case its name. The names now appear in the pytest -v output, like test_add[both_negative]. Each case passes or fails on its own, so a broken row is easy to spot in a long table — and the rows after it are still checked.

Every case gets a name

The same table, written as parametrize cases. The verbose output now lists all four cases separately — you can see exactly which cases ran and passed, and the summary says 4 passed.

Prompt
Write the same table-driven test for add with @pytest.mark.parametrize, giving each case an id, so every case appears separately in the verbose output. Show the pytest -v output with all four case lines.
Output: complete Python program

Run One Case Alone

Cases can be selected from the command line with -k, which matches against the test name and the case id:

pytest -v -k "both_negative"

Only the matching case runs; the others are deselected, not even started. This is perfect while fixing one broken case: rerun just that case until it is green, then run everything again.

Filter with -k

The same file as above, run with -k "both_negative". Only one of the four cases executes — the header counts 3 deselected and 1 selected, and the summary says 1 passed, 3 deselected.

Prompt
Using the parametrized test for add, show the output of running only one case with pytest -v -k "both_negative" — only that case should run and the other three should be deselected.
Output: complete Python program