A simple pytest extension for creating a named test suite.
Project description
Pytest (Parametrize) Suite
A tiny plugin for writing clean, easy-to-read, parametrized tests in pytest.
Why?
Pytest's parametrize
is a powerful way to write input-output testing to rapidly
expand your test coverage while minimizing the number of test assertions you must
write. Unfortunately, as the complexity of your test suite grows, it can become
difficult to keep track of individual test cases.
One way to get cleaner test output is by assigning descriptive ids
and argnames
to
each parametrized case. However, the current methodologies available result in either
very verbose setup, or difficult-to-track ids and names.
Enter pytest-parametrize-suite
. With this marker, you define your test ids and
names in-line with the values you intend to pass into your test, keeping your
identifiers tightly coupled to your test cases and encouraging a delightful testing
experience as a result.
Quickstart
Install With PIP
pip install -U pytest-parametrize-suite
Install With Poetry
poetry add --group=test pytest-parametrize-suite
Using the plugin
The plugin provides a single entrypoint in a pytest marker called suite
.
The suite
marker takes any number of keyword arguments. Each entry in should be a Mapping of
argname->argvalue
and all entries should be the same exact shape.
This gives developers the ability to
Example
Given the following module:
# iso8601.py
from __future__ import annotations
import datetime
def iso8601(
date_obj: datetime.date | datetime.datetime | datetime.time | datetime.timedelta
) -> str:
"""Format a Python date/time object into an ISO8601 string."""
if isinstance(date_obj, (datetime.date, datetime.time)):
return date_obj.isoformat()
if isinstance(date_obj, datetime.timedelta):
return timedelta_isoformat(date_obj)
raise ValueError(
f"Unrecognized value of type: {date_obj.__class__.__name__}: {date_obj}"
)
def timedelta_isoformat(delta: datetime.timedelta) -> str:
"""Why isn't this part of the stdlib?"""
usecs = abs(
(delta.days * 24 * 60 * 60 + delta.seconds) * 1000000 + delta.microseconds
)
seconds, usecs = divmod(usecs, 1000000)
minutes, seconds = divmod(seconds, 60)
hours, minutes = divmod(minutes, 60)
days, hours = divmod(hours, 24)
fmt = f"P{days}DT{hours}H{minutes}M{seconds}.{usecs:06}S"
return fmt
Writing With pytest-parametrize-suite:
# test_iso8601.py
from __future__ import annotations
import datetime
import pytest
from example.iso8601 import iso8601
@pytest.mark.suite(
datetime=dict(
given_date_obj=datetime.datetime(1970, 1, 1),
expected_date_str="1970-01-01T00:00:00",
),
date=dict(
given_date_obj=datetime.date(1970, 1, 1),
expected_date_str="1970-01-01",
),
time=dict(
given_date_obj=datetime.time(),
expected_date_str="00:00:00",
),
timedelta=dict(
given_date_obj=datetime.timedelta(1, 1, 1),
expected_date_str="P1DT1.000001S",
)
)
def test_iso8601(given_date_obj, expected_date_str):
# When
date_str = iso8601(given_date_obj)
# Then
assert date_str == expected_date_str
Writing Without pytest-parametrize-suite:
# test_iso8601.py
from __future__ import annotations
import datetime
import pytest
from example.iso8601 import iso8601
@pytest.mark.parametrize(
argnames=("given_date_obj", "expected_date_str"),
argvalues=[
(datetime.datetime(1970, 1, 1), "1970-01-01T00:00:00"),
(datetime.date(1970, 1, 1), "1970-01-01"),
(datetime.time(), "00:00:00"),
(datetime.timedelta(1, 1, 1), "P1DT1.000001S")
],
ids=["datetime", "date", "time", "timedelta"]
)
def test_iso8601(given_date_obj, expected_date_str):
# When
date_str = iso8601(given_date_obj)
# Then
assert date_str == expected_date_str
Running the test defined in the example outputs the following:
❯ pytest test_iso8601.py -v
=============================== test session starts ===============================
platform darwin -- Python 3.11.0, pytest-7.2.1, pluggy-1.0.0 -- /Users/god/Library/Caches/pypoetry/virtualenvs/pytest-parametrize-suite-TGMGi3Zp-py3.11/bin/python
cachedir: .pytest_cache
rootdir: /Users/god/PycharmProjects/pytest-parametrize-suite
plugins: parametrize-suite-23.1.0, cov-4.0.0
collected 4 items
src/pytest_parametrize_suite/example.py::test_iso8601[datetime] PASSED [ 25%]
src/pytest_parametrize_suite/example.py::test_iso8601[date] PASSED [ 50%]
src/pytest_parametrize_suite/example.py::test_iso8601[time] PASSED [ 75%]
src/pytest_parametrize_suite/example.py::test_iso8601[timedelta] PASSED [100%]
================================ 4 passed in 0.02s ================================
As you can see, we get a developer-friendly output for our parametrized tests while minimizing the amount of cognitive overhead it takes to understand and develop our test cases.
Happy testing! :white_check_mark:
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for pytest_parametrize_suite-23.1.2.tar.gz
Algorithm | Hash digest | |
---|---|---|
SHA256 | f3e11143d38694e6ddc55876070018351c570df25ce45041eec590191a907d1f |
|
MD5 | 15106fb4add248e8da417104b048f277 |
|
BLAKE2b-256 | 98aca774673d4a26cd113c4b8e1b9c92a6ef11266db8bd6444be1c9d69c08794 |
Hashes for pytest_parametrize_suite-23.1.2-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | a3a6258cef97943c8e7321099e903a4f782dac1bb8416d7bef37b9ee334dca2f |
|
MD5 | f021078faa29ef6c77eeb1017d3fdffa |
|
BLAKE2b-256 | 055739f602d4af4f391976e355dc615cdbb0c2a18df1a44af8785d0b69ad49da |