blob: 8acbd930726c08426bf819e7ca8ba3cd98e02136 [file] [log] [blame]
# Copyright 2017 The Abseil Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Tests for absl.testing.parameterized."""
from collections import abc
import sys
import unittest
from absl.testing import absltest
from absl.testing import parameterized
class MyOwnClass(object):
pass
def dummy_decorator(method):
def decorated(*args, **kwargs):
return method(*args, **kwargs)
return decorated
def dict_decorator(key, value):
"""Sample implementation of a chained decorator.
Sets a single field in a dict on a test with a dict parameter.
Uses the exposed '_ParameterizedTestIter.testcases' field to
modify arguments from previous decorators to allow decorator chains.
Args:
key: key to map to
value: value to set
Returns:
The test decorator
"""
def decorator(test_method):
# If decorating result of another dict_decorator
if isinstance(test_method, abc.Iterable):
actual_tests = []
for old_test in test_method.testcases:
# each test is a ('test_suffix', dict) tuple
new_dict = old_test[1].copy()
new_dict[key] = value
test_suffix = '%s_%s_%s' % (old_test[0], key, value)
actual_tests.append((test_suffix, new_dict))
test_method.testcases = actual_tests
return test_method
else:
test_suffix = ('_%s_%s') % (key, value)
tests_to_make = ((test_suffix, {key: value}),)
# 'test_method' here is the original test method
return parameterized.named_parameters(*tests_to_make)(test_method)
return decorator
class ParameterizedTestsTest(absltest.TestCase):
# The test testcases are nested so they're not
# picked up by the normal test case loader code.
class GoodAdditionParams(parameterized.TestCase):
@parameterized.parameters(
(1, 2, 3),
(4, 5, 9))
def test_addition(self, op1, op2, result):
self.arguments = (op1, op2, result)
self.assertEqual(result, op1 + op2)
# This class does not inherit from TestCase.
class BadAdditionParams(absltest.TestCase):
@parameterized.parameters(
(1, 2, 3),
(4, 5, 9))
def test_addition(self, op1, op2, result):
pass # Always passes, but not called w/out TestCase.
class MixedAdditionParams(parameterized.TestCase):
@parameterized.parameters(
(1, 2, 1),
(4, 5, 9))
def test_addition(self, op1, op2, result):
self.arguments = (op1, op2, result)
self.assertEqual(result, op1 + op2)
class DictionaryArguments(parameterized.TestCase):
@parameterized.parameters(
{'op1': 1, 'op2': 2, 'result': 3},
{'op1': 4, 'op2': 5, 'result': 9})
def test_addition(self, op1, op2, result):
self.assertEqual(result, op1 + op2)
class NoParameterizedTests(parameterized.TestCase):
# iterable member with non-matching name
a = 'BCD'
# member with matching name, but not a generator
testInstanceMember = None # pylint: disable=invalid-name
test_instance_member = None
# member with a matching name and iterator, but not a generator
testString = 'foo' # pylint: disable=invalid-name
test_string = 'foo'
# generator, but no matching name
def someGenerator(self): # pylint: disable=invalid-name
yield
yield
yield
def some_generator(self):
yield
yield
yield
# Generator function, but not a generator instance.
def testGenerator(self):
yield
yield
yield
def test_generator(self):
yield
yield
yield
def testNormal(self):
self.assertEqual(3, 1 + 2)
def test_normal(self):
self.assertEqual(3, 1 + 2)
class ArgumentsWithAddresses(parameterized.TestCase):
@parameterized.parameters(
(object(),),
(MyOwnClass(),),
)
def test_something(self, case):
pass
class CamelCaseNamedTests(parameterized.TestCase):
@parameterized.named_parameters(
('Interesting', 0),
)
def testSingle(self, case):
pass
@parameterized.named_parameters(
{'testcase_name': 'Interesting', 'case': 0},
)
def testDictSingle(self, case):
pass
@parameterized.named_parameters(
('Interesting', 0),
('Boring', 1),
)
def testSomething(self, case):
pass
@parameterized.named_parameters(
{'testcase_name': 'Interesting', 'case': 0},
{'testcase_name': 'Boring', 'case': 1},
)
def testDictSomething(self, case):
pass
@parameterized.named_parameters(
{'testcase_name': 'Interesting', 'case': 0},
('Boring', 1),
)
def testMixedSomething(self, case):
pass
def testWithoutParameters(self):
pass
class NamedTests(parameterized.TestCase):
"""Example tests using PEP-8 style names instead of camel-case."""
@parameterized.named_parameters(
('interesting', 0),
)
def test_single(self, case):
pass
@parameterized.named_parameters(
{'testcase_name': 'interesting', 'case': 0},
)
def test_dict_single(self, case):
pass
@parameterized.named_parameters(
('interesting', 0),
('boring', 1),
)
def test_something(self, case):
pass
@parameterized.named_parameters(
{'testcase_name': 'interesting', 'case': 0},
{'testcase_name': 'boring', 'case': 1},
)
def test_dict_something(self, case):
pass
@parameterized.named_parameters(
{'testcase_name': 'interesting', 'case': 0},
('boring', 1),
)
def test_mixed_something(self, case):
pass
def test_without_parameters(self):
pass
class ChainedTests(parameterized.TestCase):
@dict_decorator('cone', 'waffle')
@dict_decorator('flavor', 'strawberry')
def test_chained(self, dictionary):
self.assertDictEqual(dictionary, {'cone': 'waffle',
'flavor': 'strawberry'})
class SingletonListExtraction(parameterized.TestCase):
@parameterized.parameters(
(i, i * 2) for i in range(10))
def test_something(self, unused_1, unused_2):
pass
class SingletonArgumentExtraction(parameterized.TestCase):
@parameterized.parameters(1, 2, 3, 4, 5, 6)
def test_numbers(self, unused_1):
pass
@parameterized.parameters('foo', 'bar', 'baz')
def test_strings(self, unused_1):
pass
class SingletonDictArgument(parameterized.TestCase):
@parameterized.parameters({'op1': 1, 'op2': 2})
def test_something(self, op1, op2):
del op1, op2
@parameterized.parameters(
(1, 2, 3),
(4, 5, 9))
class DecoratedClass(parameterized.TestCase):
def test_add(self, arg1, arg2, arg3):
self.assertEqual(arg1 + arg2, arg3)
def test_subtract_fail(self, arg1, arg2, arg3):
self.assertEqual(arg3 + arg2, arg1)
@parameterized.parameters(
(a, b, a+b) for a in range(1, 5) for b in range(1, 5))
class GeneratorDecoratedClass(parameterized.TestCase):
def test_add(self, arg1, arg2, arg3):
self.assertEqual(arg1 + arg2, arg3)
def test_subtract_fail(self, arg1, arg2, arg3):
self.assertEqual(arg3 + arg2, arg1)
@parameterized.parameters(
(1, 2, 3),
(4, 5, 9),
)
class DecoratedBareClass(absltest.TestCase):
def test_add(self, arg1, arg2, arg3):
self.assertEqual(arg1 + arg2, arg3)
class OtherDecoratorUnnamed(parameterized.TestCase):
@dummy_decorator
@parameterized.parameters((1), (2))
def test_other_then_parameterized(self, arg1):
pass
@parameterized.parameters((1), (2))
@dummy_decorator
def test_parameterized_then_other(self, arg1):
pass
class OtherDecoratorNamed(parameterized.TestCase):
@dummy_decorator
@parameterized.named_parameters(('a', 1), ('b', 2))
def test_other_then_parameterized(self, arg1):
pass
@parameterized.named_parameters(('a', 1), ('b', 2))
@dummy_decorator
def test_parameterized_then_other(self, arg1):
pass
class OtherDecoratorNamedWithDict(parameterized.TestCase):
@dummy_decorator
@parameterized.named_parameters(
{'testcase_name': 'a', 'arg1': 1},
{'testcase_name': 'b', 'arg1': 2})
def test_other_then_parameterized(self, arg1):
pass
@parameterized.named_parameters(
{'testcase_name': 'a', 'arg1': 1},
{'testcase_name': 'b', 'arg1': 2})
@dummy_decorator
def test_parameterized_then_other(self, arg1):
pass
class UniqueDescriptiveNamesTest(parameterized.TestCase):
@parameterized.parameters(13, 13)
def test_normal(self, number):
del number
class MultiGeneratorsTestCase(parameterized.TestCase):
@parameterized.parameters((i for i in (1, 2, 3)), (i for i in (3, 2, 1)))
def test_sum(self, a, b, c):
self.assertEqual(6, sum([a, b, c]))
class NamedParametersReusableTestCase(parameterized.TestCase):
named_params_a = (
{'testcase_name': 'dict_a', 'unused_obj': 0},
('list_a', 1),
)
named_params_b = (
{'testcase_name': 'dict_b', 'unused_obj': 2},
('list_b', 3),
)
named_params_c = (
{'testcase_name': 'dict_c', 'unused_obj': 4},
('list_b', 5),
)
@parameterized.named_parameters(*(named_params_a + named_params_b))
def testSomething(self, unused_obj):
pass
@parameterized.named_parameters(*(named_params_a + named_params_c))
def testSomethingElse(self, unused_obj):
pass
class SuperclassTestCase(parameterized.TestCase):
@parameterized.parameters('foo', 'bar')
def test_name(self, name):
del name
class SubclassTestCase(SuperclassTestCase):
pass
@unittest.skipIf(
(sys.version_info[:2] == (3, 7) and sys.version_info[2] in {0, 1, 2}),
'Python 3.7.0 to 3.7.2 have a bug that breaks this test, see '
'https://bugs.python.org/issue35767')
def test_missing_inheritance(self):
ts = unittest.makeSuite(self.BadAdditionParams)
self.assertEqual(1, ts.countTestCases())
res = unittest.TestResult()
ts.run(res)
self.assertEqual(1, res.testsRun)
self.assertFalse(res.wasSuccessful())
self.assertIn('without having inherited', str(res.errors[0]))
def test_correct_extraction_numbers(self):
ts = unittest.makeSuite(self.GoodAdditionParams)
self.assertEqual(2, ts.countTestCases())
def test_successful_execution(self):
ts = unittest.makeSuite(self.GoodAdditionParams)
res = unittest.TestResult()
ts.run(res)
self.assertEqual(2, res.testsRun)
self.assertTrue(res.wasSuccessful())
def test_correct_arguments(self):
ts = unittest.makeSuite(self.GoodAdditionParams)
res = unittest.TestResult()
params = set([
(1, 2, 3),
(4, 5, 9)])
for test in ts:
test(res)
self.assertIn(test.arguments, params)
params.remove(test.arguments)
self.assertEmpty(params)
def test_recorded_failures(self):
ts = unittest.makeSuite(self.MixedAdditionParams)
self.assertEqual(2, ts.countTestCases())
res = unittest.TestResult()
ts.run(res)
self.assertEqual(2, res.testsRun)
self.assertFalse(res.wasSuccessful())
self.assertLen(res.failures, 1)
self.assertEmpty(res.errors)
def test_short_description(self):
ts = unittest.makeSuite(self.GoodAdditionParams)
short_desc = list(ts)[0].shortDescription()
location = unittest.util.strclass(self.GoodAdditionParams).replace(
'__main__.', '')
expected = ('{}.test_addition0 (1, 2, 3)\n'.format(location) +
'test_addition(1, 2, 3)')
self.assertEqual(expected, short_desc)
def test_short_description_addresses_removed(self):
ts = unittest.makeSuite(self.ArgumentsWithAddresses)
short_desc = list(ts)[0].shortDescription().split('\n')
self.assertEqual(
'test_something(<object>)', short_desc[1])
short_desc = list(ts)[1].shortDescription().split('\n')
self.assertEqual(
'test_something(<__main__.MyOwnClass>)', short_desc[1])
def test_id(self):
ts = unittest.makeSuite(self.ArgumentsWithAddresses)
self.assertEqual(
(unittest.util.strclass(self.ArgumentsWithAddresses) +
'.test_something0 (<object>)'),
list(ts)[0].id())
ts = unittest.makeSuite(self.GoodAdditionParams)
self.assertEqual(
(unittest.util.strclass(self.GoodAdditionParams) +
'.test_addition0 (1, 2, 3)'),
list(ts)[0].id())
def test_str(self):
ts = unittest.makeSuite(self.GoodAdditionParams)
test = list(ts)[0]
expected = 'test_addition0 (1, 2, 3) ({})'.format(
unittest.util.strclass(self.GoodAdditionParams))
self.assertEqual(expected, str(test))
def test_dict_parameters(self):
ts = unittest.makeSuite(self.DictionaryArguments)
res = unittest.TestResult()
ts.run(res)
self.assertEqual(2, res.testsRun)
self.assertTrue(res.wasSuccessful())
def test_no_parameterized_tests(self):
ts = unittest.makeSuite(self.NoParameterizedTests)
self.assertEqual(4, ts.countTestCases())
short_descs = [x.shortDescription() for x in list(ts)]
full_class_name = unittest.util.strclass(self.NoParameterizedTests)
full_class_name = full_class_name.replace('__main__.', '')
self.assertSameElements(
[
'{}.testGenerator'.format(full_class_name),
'{}.test_generator'.format(full_class_name),
'{}.testNormal'.format(full_class_name),
'{}.test_normal'.format(full_class_name),
],
short_descs)
def test_successful_product_test_testgrid(self):
class GoodProductTestCase(parameterized.TestCase):
@parameterized.product(
num=(0, 20, 80),
modulo=(2, 4),
expected=(0,)
)
def testModuloResult(self, num, modulo, expected):
self.assertEqual(expected, num % modulo)
ts = unittest.makeSuite(GoodProductTestCase)
res = unittest.TestResult()
ts.run(res)
self.assertEqual(ts.countTestCases(), 6)
self.assertEqual(res.testsRun, 6)
self.assertTrue(res.wasSuccessful())
def test_successful_product_test_kwarg_seqs(self):
class GoodProductTestCase(parameterized.TestCase):
@parameterized.product((dict(num=0), dict(num=20), dict(num=0)),
(dict(modulo=2), dict(modulo=4)),
(dict(expected=0),))
def testModuloResult(self, num, modulo, expected):
self.assertEqual(expected, num % modulo)
ts = unittest.makeSuite(GoodProductTestCase)
res = unittest.TestResult()
ts.run(res)
self.assertEqual(ts.countTestCases(), 6)
self.assertEqual(res.testsRun, 6)
self.assertTrue(res.wasSuccessful())
def test_successful_product_test_kwarg_seq_and_testgrid(self):
class GoodProductTestCase(parameterized.TestCase):
@parameterized.product((dict(
num=5, modulo=3, expected=2), dict(num=7, modulo=4, expected=3)),
dtype=(int, float))
def testModuloResult(self, num, dtype, modulo, expected):
self.assertEqual(expected, dtype(num) % modulo)
ts = unittest.makeSuite(GoodProductTestCase)
res = unittest.TestResult()
ts.run(res)
self.assertEqual(ts.countTestCases(), 4)
self.assertEqual(res.testsRun, 4)
self.assertTrue(res.wasSuccessful())
def test_inconsistent_arg_names_in_kwargs_seq(self):
with self.assertRaisesRegex(AssertionError, 'must all have the same keys'):
class BadProductParams(parameterized.TestCase): # pylint: disable=unused-variable
@parameterized.product((dict(num=5, modulo=3), dict(num=7, modula=2)),
dtype=(int, float))
def test_something(self):
pass # not called because argnames are not the same
def test_duplicate_arg_names_in_kwargs_seqs(self):
with self.assertRaisesRegex(AssertionError, 'must all have distinct'):
class BadProductParams(parameterized.TestCase): # pylint: disable=unused-variable
@parameterized.product((dict(num=5, modulo=3), dict(num=7, modulo=4)),
(dict(foo='bar', num=5), dict(foo='baz', num=7)),
dtype=(int, float))
def test_something(self):
pass # not called because `num` is specified twice
def test_duplicate_arg_names_in_kwargs_seq_and_testgrid(self):
with self.assertRaisesRegex(AssertionError, 'duplicate argument'):
class BadProductParams(parameterized.TestCase): # pylint: disable=unused-variable
@parameterized.product(
(dict(num=5, modulo=3), dict(num=7, modulo=4)),
(dict(foo='bar'), dict(foo='baz')),
dtype=(int, float),
foo=('a', 'b'),
)
def test_something(self):
pass # not called because `foo` is specified twice
def test_product_recorded_failures(self):
class MixedProductTestCase(parameterized.TestCase):
@parameterized.product(
num=(0, 10, 20),
modulo=(2, 4),
expected=(0,)
)
def testModuloResult(self, num, modulo, expected):
self.assertEqual(expected, num % modulo)
ts = unittest.makeSuite(MixedProductTestCase)
self.assertEqual(6, ts.countTestCases())
res = unittest.TestResult()
ts.run(res)
self.assertEqual(res.testsRun, 6)
self.assertFalse(res.wasSuccessful())
self.assertLen(res.failures, 1)
self.assertEmpty(res.errors)
def test_mismatched_product_parameter(self):
class MismatchedProductParam(parameterized.TestCase):
@parameterized.product(
a=(1, 2),
mismatch=(1, 2)
)
# will fail because of mismatch in parameter names.
def test_something(self, a, b):
pass
ts = unittest.makeSuite(MismatchedProductParam)
res = unittest.TestResult()
ts.run(res)
self.assertEqual(res.testsRun, 4)
self.assertFalse(res.wasSuccessful())
self.assertLen(res.errors, 4)
def test_no_test_error_empty_product_parameter(self):
with self.assertRaises(parameterized.NoTestsError):
class EmptyProductParam(parameterized.TestCase): # pylint: disable=unused-variable
@parameterized.product(arg1=[1, 2], arg2=[])
def test_something(self, arg1, arg2):
pass # not called because arg2 has empty list of values.
def test_bad_product_parameters(self):
with self.assertRaisesRegex(AssertionError, 'must be given as list or'):
class BadProductParams(parameterized.TestCase): # pylint: disable=unused-variable
@parameterized.product(arg1=[1, 2], arg2='abcd')
def test_something(self, arg1, arg2):
pass # not called because arg2 is not list or tuple.
def test_generator_tests_disallowed(self):
with self.assertRaisesRegex(RuntimeError, 'generated.*without'):
class GeneratorTests(parameterized.TestCase): # pylint: disable=unused-variable
test_generator_method = (lambda self: None for _ in range(10))
def test_named_parameters_run(self):
ts = unittest.makeSuite(self.NamedTests)
self.assertEqual(9, ts.countTestCases())
res = unittest.TestResult()
ts.run(res)
self.assertEqual(9, res.testsRun)
self.assertTrue(res.wasSuccessful())
def test_named_parameters_id(self):
ts = sorted(unittest.makeSuite(self.CamelCaseNamedTests),
key=lambda t: t.id())
self.assertLen(ts, 9)
full_class_name = unittest.util.strclass(self.CamelCaseNamedTests)
self.assertEqual(
full_class_name + '.testDictSingleInteresting',
ts[0].id())
self.assertEqual(
full_class_name + '.testDictSomethingBoring',
ts[1].id())
self.assertEqual(
full_class_name + '.testDictSomethingInteresting',
ts[2].id())
self.assertEqual(
full_class_name + '.testMixedSomethingBoring',
ts[3].id())
self.assertEqual(
full_class_name + '.testMixedSomethingInteresting',
ts[4].id())
self.assertEqual(
full_class_name + '.testSingleInteresting',
ts[5].id())
self.assertEqual(
full_class_name + '.testSomethingBoring',
ts[6].id())
self.assertEqual(
full_class_name + '.testSomethingInteresting',
ts[7].id())
self.assertEqual(
full_class_name + '.testWithoutParameters',
ts[8].id())
def test_named_parameters_id_with_underscore_case(self):
ts = sorted(unittest.makeSuite(self.NamedTests),
key=lambda t: t.id())
self.assertLen(ts, 9)
full_class_name = unittest.util.strclass(self.NamedTests)
self.assertEqual(
full_class_name + '.test_dict_single_interesting',
ts[0].id())
self.assertEqual(
full_class_name + '.test_dict_something_boring',
ts[1].id())
self.assertEqual(
full_class_name + '.test_dict_something_interesting',
ts[2].id())
self.assertEqual(
full_class_name + '.test_mixed_something_boring',
ts[3].id())
self.assertEqual(
full_class_name + '.test_mixed_something_interesting',
ts[4].id())
self.assertEqual(
full_class_name + '.test_single_interesting',
ts[5].id())
self.assertEqual(
full_class_name + '.test_something_boring',
ts[6].id())
self.assertEqual(
full_class_name + '.test_something_interesting',
ts[7].id())
self.assertEqual(
full_class_name + '.test_without_parameters',
ts[8].id())
def test_named_parameters_short_description(self):
ts = sorted(unittest.makeSuite(self.NamedTests),
key=lambda t: t.id())
actual = {t._testMethodName: t.shortDescription() for t in ts}
expected = {
'test_dict_single_interesting': 'case=0',
'test_dict_something_boring': 'case=1',
'test_dict_something_interesting': 'case=0',
'test_mixed_something_boring': '1',
'test_mixed_something_interesting': 'case=0',
'test_something_boring': '1',
'test_something_interesting': '0',
}
for test_name, param_repr in expected.items():
short_desc = actual[test_name].split('\n')
self.assertIn(test_name, short_desc[0])
self.assertEqual('{}({})'.format(test_name, param_repr), short_desc[1])
def test_load_tuple_named_test(self):
loader = unittest.TestLoader()
ts = list(loader.loadTestsFromName('NamedTests.test_something_interesting',
module=self))
self.assertLen(ts, 1)
self.assertEndsWith(ts[0].id(), '.test_something_interesting')
def test_load_dict_named_test(self):
loader = unittest.TestLoader()
ts = list(
loader.loadTestsFromName(
'NamedTests.test_dict_something_interesting', module=self))
self.assertLen(ts, 1)
self.assertEndsWith(ts[0].id(), '.test_dict_something_interesting')
def test_load_mixed_named_test(self):
loader = unittest.TestLoader()
ts = list(
loader.loadTestsFromName(
'NamedTests.test_mixed_something_interesting', module=self))
self.assertLen(ts, 1)
self.assertEndsWith(ts[0].id(), '.test_mixed_something_interesting')
def test_duplicate_named_test_fails(self):
with self.assertRaises(parameterized.DuplicateTestNameError):
class _(parameterized.TestCase):
@parameterized.named_parameters(
('Interesting', 0),
('Interesting', 1),
)
def test_something(self, unused_obj):
pass
def test_duplicate_dict_named_test_fails(self):
with self.assertRaises(parameterized.DuplicateTestNameError):
class _(parameterized.TestCase):
@parameterized.named_parameters(
{'testcase_name': 'Interesting', 'unused_obj': 0},
{'testcase_name': 'Interesting', 'unused_obj': 1},
)
def test_dict_something(self, unused_obj):
pass
def test_duplicate_mixed_named_test_fails(self):
with self.assertRaises(parameterized.DuplicateTestNameError):
class _(parameterized.TestCase):
@parameterized.named_parameters(
{'testcase_name': 'Interesting', 'unused_obj': 0},
('Interesting', 1),
)
def test_mixed_something(self, unused_obj):
pass
def test_named_test_with_no_name_fails(self):
with self.assertRaises(RuntimeError):
class _(parameterized.TestCase):
@parameterized.named_parameters(
(0,),
)
def test_something(self, unused_obj):
pass
def test_named_test_dict_with_no_name_fails(self):
with self.assertRaises(RuntimeError):
class _(parameterized.TestCase):
@parameterized.named_parameters(
{'unused_obj': 0},
)
def test_something(self, unused_obj):
pass
def test_parameterized_test_iter_has_testcases_property(self):
@parameterized.parameters(1, 2, 3, 4, 5, 6)
def test_something(unused_self, unused_obj): # pylint: disable=invalid-name
pass
expected_testcases = [1, 2, 3, 4, 5, 6]
self.assertTrue(hasattr(test_something, 'testcases'))
self.assertCountEqual(expected_testcases, test_something.testcases)
def test_chained_decorator(self):
ts = unittest.makeSuite(self.ChainedTests)
self.assertEqual(1, ts.countTestCases())
test = next(t for t in ts)
self.assertTrue(hasattr(test, 'test_chained_flavor_strawberry_cone_waffle'))
res = unittest.TestResult()
ts.run(res)
self.assertEqual(1, res.testsRun)
self.assertTrue(res.wasSuccessful())
def test_singleton_list_extraction(self):
ts = unittest.makeSuite(self.SingletonListExtraction)
res = unittest.TestResult()
ts.run(res)
self.assertEqual(10, res.testsRun)
self.assertTrue(res.wasSuccessful())
def test_singleton_argument_extraction(self):
ts = unittest.makeSuite(self.SingletonArgumentExtraction)
res = unittest.TestResult()
ts.run(res)
self.assertEqual(9, res.testsRun)
self.assertTrue(res.wasSuccessful())
def test_singleton_dict_argument(self):
ts = unittest.makeSuite(self.SingletonDictArgument)
res = unittest.TestResult()
ts.run(res)
self.assertEqual(1, res.testsRun)
self.assertTrue(res.wasSuccessful())
def test_decorated_bare_class(self):
ts = unittest.makeSuite(self.DecoratedBareClass)
res = unittest.TestResult()
ts.run(res)
self.assertEqual(2, res.testsRun)
self.assertTrue(res.wasSuccessful(), msg=str(res.failures))
def test_decorated_class(self):
ts = unittest.makeSuite(self.DecoratedClass)
res = unittest.TestResult()
ts.run(res)
self.assertEqual(4, res.testsRun)
self.assertLen(res.failures, 2)
def test_generator_decorated_class(self):
ts = unittest.makeSuite(self.GeneratorDecoratedClass)
res = unittest.TestResult()
ts.run(res)
self.assertEqual(32, res.testsRun)
self.assertLen(res.failures, 16)
def test_no_duplicate_decorations(self):
with self.assertRaises(AssertionError):
@parameterized.parameters(1, 2, 3, 4)
class _(parameterized.TestCase):
@parameterized.parameters(5, 6, 7, 8)
def test_something(self, unused_obj):
pass
def test_double_class_decorations_not_supported(self):
@parameterized.parameters('foo', 'bar')
class SuperclassWithClassDecorator(parameterized.TestCase):
def test_name(self, name):
del name
with self.assertRaises(AssertionError):
@parameterized.parameters('foo', 'bar')
class SubclassWithClassDecorator(SuperclassWithClassDecorator):
pass
del SubclassWithClassDecorator
def test_other_decorator_ordering_unnamed(self):
ts = unittest.makeSuite(self.OtherDecoratorUnnamed)
res = unittest.TestResult()
ts.run(res)
# Two for when the parameterized tests call the skip wrapper.
# One for when the skip wrapper is called first and doesn't iterate.
self.assertEqual(3, res.testsRun)
self.assertFalse(res.wasSuccessful())
self.assertEmpty(res.failures)
# One error from test_other_then_parameterized.
self.assertLen(res.errors, 1)
def test_other_decorator_ordering_named(self):
ts = unittest.makeSuite(self.OtherDecoratorNamed)
# Verify it generates the test method names from the original test method.
for test in ts: # There is only one test.
ts_attributes = dir(test)
self.assertIn('test_parameterized_then_other_a', ts_attributes)
self.assertIn('test_parameterized_then_other_b', ts_attributes)
res = unittest.TestResult()
ts.run(res)
# Two for when the parameterized tests call the skip wrapper.
# One for when the skip wrapper is called first and doesn't iterate.
self.assertEqual(3, res.testsRun)
self.assertFalse(res.wasSuccessful())
self.assertEmpty(res.failures)
# One error from test_other_then_parameterized.
self.assertLen(res.errors, 1)
def test_other_decorator_ordering_named_with_dict(self):
ts = unittest.makeSuite(self.OtherDecoratorNamedWithDict)
# Verify it generates the test method names from the original test method.
for test in ts: # There is only one test.
ts_attributes = dir(test)
self.assertIn('test_parameterized_then_other_a', ts_attributes)
self.assertIn('test_parameterized_then_other_b', ts_attributes)
res = unittest.TestResult()
ts.run(res)
# Two for when the parameterized tests call the skip wrapper.
# One for when the skip wrapper is called first and doesn't iterate.
self.assertEqual(3, res.testsRun)
self.assertFalse(res.wasSuccessful())
self.assertEmpty(res.failures)
# One error from test_other_then_parameterized.
self.assertLen(res.errors, 1)
def test_no_test_error_empty_parameters(self):
with self.assertRaises(parameterized.NoTestsError):
@parameterized.parameters()
def test_something():
pass
del test_something
def test_no_test_error_empty_generator(self):
with self.assertRaises(parameterized.NoTestsError):
@parameterized.parameters((i for i in []))
def test_something():
pass
del test_something
def test_unique_descriptive_names(self):
class RecordSuccessTestsResult(unittest.TestResult):
def __init__(self, *args, **kwargs):
super(RecordSuccessTestsResult, self).__init__(*args, **kwargs)
self.successful_tests = []
def addSuccess(self, test):
self.successful_tests.append(test)
ts = unittest.makeSuite(self.UniqueDescriptiveNamesTest)
res = RecordSuccessTestsResult()
ts.run(res)
self.assertTrue(res.wasSuccessful())
self.assertEqual(2, res.testsRun)
test_ids = [test.id() for test in res.successful_tests]
full_class_name = unittest.util.strclass(self.UniqueDescriptiveNamesTest)
expected_test_ids = [
full_class_name + '.test_normal0 (13)',
full_class_name + '.test_normal1 (13)',
]
self.assertTrue(test_ids)
self.assertCountEqual(expected_test_ids, test_ids)
def test_multi_generators(self):
ts = unittest.makeSuite(self.MultiGeneratorsTestCase)
res = unittest.TestResult()
ts.run(res)
self.assertEqual(2, res.testsRun)
self.assertTrue(res.wasSuccessful(), msg=str(res.failures))
def test_named_parameters_reusable(self):
ts = unittest.makeSuite(self.NamedParametersReusableTestCase)
res = unittest.TestResult()
ts.run(res)
self.assertEqual(8, res.testsRun)
self.assertTrue(res.wasSuccessful(), msg=str(res.failures))
def test_subclass_inherits_superclass_test_params_reprs(self):
self.assertEqual(
{'test_name0': "('foo')", 'test_name1': "('bar')"},
self.SuperclassTestCase._test_params_reprs)
self.assertEqual(
{'test_name0': "('foo')", 'test_name1': "('bar')"},
self.SubclassTestCase._test_params_reprs)
def _decorate_with_side_effects(func, self):
self.sideeffect = True
func(self)
class CoopMetaclassCreationTest(absltest.TestCase):
class TestBase(absltest.TestCase):
# This test simulates a metaclass that sets some attribute ('sideeffect')
# on each member of the class that starts with 'test'. The test code then
# checks that this attribute exists when the custom metaclass and
# TestGeneratorMetaclass are combined with cooperative inheritance.
# The attribute has to be set in the __init__ method of the metaclass,
# since the TestGeneratorMetaclass already overrides __new__. Only one
# base metaclass can override __new__, but all can provide custom __init__
# methods.
class __metaclass__(type): # pylint: disable=g-bad-name
def __init__(cls, name, bases, dct):
type.__init__(cls, name, bases, dct)
for member_name, obj in dct.items():
if member_name.startswith('test'):
setattr(cls, member_name,
lambda self, f=obj: _decorate_with_side_effects(f, self))
class MyParams(parameterized.CoopTestCase(TestBase)):
@parameterized.parameters(
(1, 2, 3),
(4, 5, 9))
def test_addition(self, op1, op2, result):
self.assertEqual(result, op1 + op2)
class MySuite(unittest.TestSuite):
# Under Python 3.4 the TestCases in the suite's list of tests to run are
# destroyed and replaced with None after successful execution by default.
# This disables that behavior.
_cleanup = False
def test_successful_execution(self):
ts = unittest.makeSuite(self.MyParams)
res = unittest.TestResult()
ts.run(res)
self.assertEqual(2, res.testsRun)
self.assertTrue(res.wasSuccessful())
def test_metaclass_side_effects(self):
ts = unittest.makeSuite(self.MyParams, suiteClass=self.MySuite)
res = unittest.TestResult()
ts.run(res)
self.assertTrue(list(ts)[0].sideeffect)
if __name__ == '__main__':
absltest.main()