Skip to content

_parameterized

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 (which is modified internally) and the arguments for the specific invocation, which are part of the string returned by the shortDescription() method on test cases.

The id method of the test, used internally by the unittest framework, is also modified to show the arguments. 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>'. For even more descriptive names, especially in test logs, you can use the named_parameters decorator. In this case, only tuples are supported, and the first parameters has to 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, strings.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, arg2, 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 argument does not need to be wrapped into a tuple:

class NegativeNumberExample(parameterized.TestCase): @parameterized.parameters( -1, -3, -4, -5 ) def testIsNegative(self, arg): self.assertTrue(IsNegative(arg))

TestCase

Bases: TestCase

Base class for test cases using the parameters decorator.

Source code in client/ayon_hiero/vendor/google/protobuf/internal/_parameterized.py
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
class TestCase(unittest.TestCase, metaclass=TestGeneratorMetaclass):
  """Base class for test cases using the parameters decorator."""

  def _OriginalName(self):
    return self._testMethodName.split(_SEPARATOR)[0]

  def __str__(self):
    return '%s (%s)' % (self._OriginalName(), _StrClass(self.__class__))

  def id(self):  # pylint: disable=invalid-name
    """Returns the descriptive ID of the test.

    This is used internally by the unittesting framework to get a name
    for the test to be used in reports.

    Returns:
      The test id.
    """
    return '%s.%s%s' % (_StrClass(self.__class__),
                        self._OriginalName(),
                        self._id_suffix.get(self._testMethodName, ''))

id()

Returns the descriptive ID of the test.

This is used internally by the unittesting framework to get a name for the test to be used in reports.

Returns:

Type Description

The test id.

Source code in client/ayon_hiero/vendor/google/protobuf/internal/_parameterized.py
398
399
400
401
402
403
404
405
406
407
408
409
def id(self):  # pylint: disable=invalid-name
  """Returns the descriptive ID of the test.

  This is used internally by the unittesting framework to get a name
  for the test to be used in reports.

  Returns:
    The test id.
  """
  return '%s.%s%s' % (_StrClass(self.__class__),
                      self._OriginalName(),
                      self._id_suffix.get(self._testMethodName, ''))

TestGeneratorMetaclass

Bases: type

Metaclass for test cases with test generators.

A test generator is an iterable in a testcase that produces callables. These callables must be single-argument methods. These methods are injected into the class namespace and the original iterable is removed. If the name of the iterable conforms to the test pattern, the injected methods will be picked up as tests by the unittest framework.

In general, it is supposed to be used in conjunction with the parameters decorator.

Source code in client/ayon_hiero/vendor/google/protobuf/internal/_parameterized.py
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
class TestGeneratorMetaclass(type):
  """Metaclass for test cases with test generators.

  A test generator is an iterable in a testcase that produces callables. These
  callables must be single-argument methods. These methods are injected into
  the class namespace and the original iterable is removed. If the name of the
  iterable conforms to the test pattern, the injected methods will be picked
  up as tests by the unittest framework.

  In general, it is supposed to be used in conjunction with the
  parameters decorator.
  """

  def __new__(mcs, class_name, bases, dct):
    dct['_id_suffix'] = id_suffix = {}
    for name, obj in dct.copy().items():
      if (name.startswith(unittest.TestLoader.testMethodPrefix) and
          _NonStringIterable(obj)):
        iterator = iter(obj)
        dct.pop(name)
        _UpdateClassDictForParamTestCase(dct, id_suffix, name, iterator)

    return type.__new__(mcs, class_name, bases, dct)

CoopTestCase(other_base_class)

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:

import google3 import mox

from google3.testing.pybase import parameterized

class ExampleTest(parameterized.CoopTestCase(mox.MoxTestBase)): ...

Parameters:

Name Type Description Default
other_base_class

(class) A test case base class.

required

Returns:

Type Description

A new class object.

Source code in client/ayon_hiero/vendor/google/protobuf/internal/_parameterized.py
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
def CoopTestCase(other_base_class):
  """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:

    import google3
    import mox

    from google3.testing.pybase import parameterized

    class ExampleTest(parameterized.CoopTestCase(mox.MoxTestBase)):
      ...

  Args:
    other_base_class: (class) A test case base class.

  Returns:
    A new class object.
  """
  metaclass = type(
      'CoopMetaclass',
      (other_base_class.__metaclass__,
       TestGeneratorMetaclass), {})
  return metaclass(
      'CoopTestCase',
      (other_base_class, TestCase), {})

named_parameters(*testcases)

A decorator for creating parameterized tests.

See the module docstring for a usage example. The first element of each parameter tuple should be a string and will be appended to the name of the test method.

Parameters:

Name Type Description Default
*testcases

Parameters for the decorated method, either a single iterable, or a list of tuples.

()

Returns:

Type Description

A test generator to be handled by TestGeneratorMetaclass.

Source code in client/ayon_hiero/vendor/google/protobuf/internal/_parameterized.py
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
def named_parameters(*testcases):  # pylint: disable=invalid-name
  """A decorator for creating parameterized tests.

  See the module docstring for a usage example. The first element of
  each parameter tuple should be a string and will be appended to the
  name of the test method.

  Args:
    *testcases: Parameters for the decorated method, either a single
                iterable, or a list of tuples.

  Returns:
     A test generator to be handled by TestGeneratorMetaclass.
  """
  return _ParameterDecorator(_FIRST_ARG, testcases)

parameters(*testcases)

A decorator for creating parameterized tests.

See the module docstring for a usage example. Args: *testcases: Parameters for the decorated method, either a single iterable, or a list of tuples/dicts/objects (for tests with only one argument).

Returns:

Type Description

A test generator to be handled by TestGeneratorMetaclass.

Source code in client/ayon_hiero/vendor/google/protobuf/internal/_parameterized.py
310
311
312
313
314
315
316
317
318
319
320
321
322
def parameters(*testcases):  # pylint: disable=invalid-name
  """A decorator for creating parameterized tests.

  See the module docstring for a usage example.
  Args:
    *testcases: Parameters for the decorated method, either a single
                iterable, or a list of tuples/dicts/objects (for tests
                with only one argument).

  Returns:
     A test generator to be handled by TestGeneratorMetaclass.
  """
  return _ParameterDecorator(_ARGUMENT_REPR, testcases)