mirror of https://github.com/python/cpython
40 lines
905 B
Python
40 lines
905 B
Python
import types
|
|
import functools
|
|
|
|
from ._itertools import always_iterable
|
|
|
|
|
|
def parameterize(names, value_groups):
|
|
"""
|
|
Decorate a test method to run it as a set of subtests.
|
|
|
|
Modeled after pytest.parametrize.
|
|
"""
|
|
|
|
def decorator(func):
|
|
@functools.wraps(func)
|
|
def wrapped(self):
|
|
for values in value_groups:
|
|
resolved = map(Invoked.eval, always_iterable(values))
|
|
params = dict(zip(always_iterable(names), resolved))
|
|
with self.subTest(**params):
|
|
func(self, **params)
|
|
|
|
return wrapped
|
|
|
|
return decorator
|
|
|
|
|
|
class Invoked(types.SimpleNamespace):
|
|
"""
|
|
Wrap a function to be invoked for each usage.
|
|
"""
|
|
|
|
@classmethod
|
|
def wrap(cls, func):
|
|
return cls(func=func)
|
|
|
|
@classmethod
|
|
def eval(cls, cand):
|
|
return cand.func() if isinstance(cand, cls) else cand
|