Files
opendbc-meb/opendbc/testing.py
2026-03-10 23:10:12 -07:00

60 lines
1.6 KiB
Python

import functools
import sys
def parameterized(argnames, argvalues):
"""Method decorator that runs a test once per parameter set using subTest.
Usage:
@parameterized("x, y", [(1, 2), (3, 4)])
def test_add(self, x, y): ...
@parameterized("car_model, fingerprints", FINGERPRINTS.items())
def test_fw(self, car_model, fingerprints): ...
"""
if isinstance(argnames, str):
argnames = [a.strip() for a in argnames.split(',')]
def decorator(func):
@functools.wraps(func)
def wrapper(self):
for values in argvalues:
if not isinstance(values, (tuple, list)):
values = (values,)
kwargs = dict(zip(argnames, values, strict=True))
with self.subTest(**kwargs):
func(self, **kwargs)
return wrapper
return decorator
def parameterized_class(attrs, values=None):
"""Class decorator that generates subclasses with different class attributes.
Usage:
@parameterized_class([{"x": 1}, {"x": 2}])
@parameterized_class('x', [(1,), (2,)])
"""
if isinstance(attrs, str):
attrs = [attrs]
params = [dict(zip(attrs, v, strict=True)) for v in values]
else:
params = attrs
def decorator(cls):
module = sys.modules[cls.__module__]
for param_set in params:
name = f"{cls.__name__}_{'_'.join(str(v) for v in param_set.values())}"
new_cls = type(name, (cls,), param_set)
new_cls.__qualname__ = name
new_cls.__module__ = cls.__module__
new_cls.__test__ = True
setattr(module, name, new_cls)
cls.__test__ = False
return cls
return decorator