absl.testing.parameterized module
Adds support for parameterized tests to Python’s unittest TestCase class.
A parameterized test is a method in a test case that is invoked with different argument tuples.
A simple example:
class AdditionExample(parameterized.TestCase):
@parameterized.parameters(
(1, 2, 3),
(4, 5, 9),
(1, 1, 3))
def testAddition(self, op1, op2, result):
self.assertEqual(result, op1 + op2)
Each invocation is a separate test case and properly isolated just like a normal test method, with its own setUp/tearDown cycle. In the example above, there are three separate testcases, one of which will fail due to an assertion error (1 + 1 != 3).
Parameters for individual test cases can be tuples (with positional parameters) or dictionaries (with named parameters):
class AdditionExample(parameterized.TestCase):
@parameterized.parameters(
{'op1': 1, 'op2': 2, 'result': 3},
{'op1': 4, 'op2': 5, 'result': 9},
)
def testAddition(self, op1, op2, result):
self.assertEqual(result, op1 + op2)
If a parameterized test fails, the error message will show the original test name and the parameters for that test.
The id method of the test, used internally by the unittest framework, is also modified to show the arguments (but note that the name reported by id() doesn’t match the actual test name, see below). To make sure that test names stay the same across several invocations, object representations like:
>>> class Foo(object):
... pass
>>> repr(Foo())
'<__main__.Foo object at 0x23d8610>'
are turned into __main__.Foo. When selecting a subset of test cases to run
on the command-line, the test cases contain an index suffix for each argument
in the order they were passed to parameters() (eg. testAddition0,
testAddition1, etc.) This naming scheme is subject to change; for more reliable
and stable names, especially in test logs, use named_parameters() instead.
Tests using named_parameters() are similar to parameters(), except
only tuples or dicts of args are supported. For tuples, the first parameter arg
has to be a string (or an object that returns an apt name when converted via
str()). For dicts, a value for the key testcase_name must be present and
must be a string (or an object that returns an apt name when converted via
str()):
class NamedExample(parameterized.TestCase):
@parameterized.named_parameters(
('Normal', 'aa', 'aaa', True),
('EmptyPrefix', '', 'abc', True),
('BothEmpty', '', '', True))
def testStartsWith(self, prefix, string, result):
self.assertEqual(result, string.startswith(prefix))
class NamedExample(parameterized.TestCase):
@parameterized.named_parameters(
{'testcase_name': 'Normal',
'result': True, 'string': 'aaa', 'prefix': 'aa'},
{'testcase_name': 'EmptyPrefix',
'result': True, 'string': 'abc', 'prefix': ''},
{'testcase_name': 'BothEmpty',
'result': True, 'string': '', 'prefix': ''})
def testStartsWith(self, prefix, string, result):
self.assertEqual(result, string.startswith(prefix))
Named tests also have the benefit that they can be run individually from the command line:
$ testmodule.py NamedExample.testStartsWithNormal
.
--------------------------------------------------------------------
Ran 1 test in 0.000s
OK
Parameterized Classes
If invocation arguments are shared across test methods in a single TestCase class, instead of decorating all test methods individually, the class itself can be decorated:
@parameterized.parameters(
(1, 2, 3),
(4, 5, 9))
class ArithmeticTest(parameterized.TestCase):
def testAdd(self, arg1, arg2, result):
self.assertEqual(arg1 + arg2, result)
def testSubtract(self, arg1, arg2, result):
self.assertEqual(result - arg1, arg2)
Inputs from Iterables
If parameters should be shared across several test cases, or are dynamically created from other sources, a single non-tuple iterable can be passed into the decorator. This iterable will be used to obtain the test cases:
class AdditionExample(parameterized.TestCase):
@parameterized.parameters(
c.op1, c.op2, c.result for c in testcases
)
def testAddition(self, op1, op2, result):
self.assertEqual(result, op1 + op2)
Single-Argument Test Methods
If a test method takes only one argument, the single arguments must not be wrapped into a tuple:
class NegativeNumberExample(parameterized.TestCase):
@parameterized.parameters(
-1, -3, -4, -5
)
def testIsNegative(self, arg):
self.assertTrue(IsNegative(arg))
List/tuple as a Single Argument
If a test method takes a single argument of a list/tuple, it must be wrapped inside a tuple:
class ZeroSumExample(parameterized.TestCase):
@parameterized.parameters(
([-1, 0, 1], ),
([-2, 0, 2], ),
)
def testSumIsZero(self, arg):
self.assertEqual(0, sum(arg))
Cartesian product of Parameter Values as Parametrized Test Cases
If required to test method over a cartesian product of parameters, parameterized.product may be used to facilitate generation of parameters test combinations:
class TestModuloExample(parameterized.TestCase):
@parameterized.product(
num=[0, 20, 80],
modulo=[2, 4],
expected=[0]
)
def testModuloResult(self, num, modulo, expected):
self.assertEqual(expected, num % modulo)
This results in 6 test cases being created - one for each combination of the parameters. It is also possible to supply sequences of keyword argument dicts as elements of the cartesian product:
@parameterized.product(
(dict(num=5, modulo=3, expected=2),
dict(num=7, modulo=4, expected=3)),
dtype=(int, float)
)
def testModuloResult(self, num, modulo, expected, dtype):
self.assertEqual(expected, dtype(num) % modulo)
This results in 4 test cases being created - for each of the two sets of test data (supplied as kwarg dicts) and for each of the two data types (supplied as a named parameter). Multiple keyword argument dicts may be supplied if required.
Async Support
If a test needs to call async functions, it can inherit from both parameterized.TestCase and another TestCase that supports async calls, such as [asynctest](https://github.com/Martiusweb/asynctest):
import asynctest
class AsyncExample(parameterized.TestCase, asynctest.TestCase):
@parameterized.parameters(
('a', 1),
('b', 2),
)
async def testSomeAsyncFunction(self, arg, expected):
actual = await someAsyncFunction(arg)
self.assertEqual(actual, expected)
- absl.testing.parameterized.CoopTestCase(other_base_class)[source]
Returns a new base class with a cooperative metaclass base.
This enables the TestCase to be used in combination with other base classes that have custom metaclasses, such as
mox.MoxTestBase.Only works with metaclasses that do not override
type.__new__.Example:
from absl.testing import parameterized class ExampleTest(parameterized.CoopTestCase(OtherTestCase)): ...
- Parameters:
other_base_class – (class) A test case base class.
- Returns:
A new class object.
- exception absl.testing.parameterized.DuplicateTestNameError(test_class_name, new_test_name, original_test_name)[source]
Bases:
ExceptionRaised when a parameterized test has the same test name multiple times.
- exception absl.testing.parameterized.NoTestsError[source]
Bases:
ExceptionRaised when parameterized decorators do not generate any tests.
- class absl.testing.parameterized.TestCase(*args, **kwargs)[source]
Bases:
TestCaseBase class for test cases using the parameters decorator.
- class absl.testing.parameterized.TestGeneratorMetaclass(class_name, bases, dct)[source]
Bases:
typeMetaclass for adding tests generated by parameterized decorators.
- absl.testing.parameterized.named_parameters(*testcases)[source]
A decorator for creating parameterized tests.
See the module docstring for a usage example. For every parameter tuple passed, the first element of the tuple should be a string and will be appended to the name of the test method. Each parameter dict passed must have a value for the key “testcase_name”, the string representation of that value will be appended to the name of the test method.
- Parameters:
*testcases – Parameters for the decorated method, either a single iterable, or a list of tuples or dicts.
- Raises:
NoTestsError – Raised when the decorator generates no tests.
- Returns:
A test generator to be handled by TestGeneratorMetaclass.
- absl.testing.parameterized.parameters(*testcases)[source]
A decorator for creating parameterized tests.
See the module docstring for a usage example.
- Parameters:
*testcases – Parameters for the decorated method, either a single iterable, or a list of tuples/dicts/objects (for tests with only one argument).
- Raises:
NoTestsError – Raised when the decorator generates no tests.
- Returns:
A test generator to be handled by TestGeneratorMetaclass.
- absl.testing.parameterized.product(*kwargs_seqs, **testgrid)[source]
A decorator for running tests over cartesian product of parameters values.
See the module docstring for a usage example. The test will be run for every possible combination of the parameters.
- Parameters:
*kwargs_seqs – Each positional parameter is a sequence of keyword arg dicts; every test case generated will include exactly one kwargs dict from each positional parameter; these will then be merged to form an overall list of arguments for the test case.
**testgrid – A mapping of parameter names and their possible values. Possible values should given as either a list or a tuple.
- Raises:
NoTestsError – Raised when the decorator generates no tests.
- Returns:
A test generator to be handled by TestGeneratorMetaclass.