aboutsummaryrefslogtreecommitdiff
path: root/absl/testing/tests/flagsaver_test.py
diff options
context:
space:
mode:
Diffstat (limited to 'absl/testing/tests/flagsaver_test.py')
-rw-r--r--absl/testing/tests/flagsaver_test.py681
1 files changed, 422 insertions, 259 deletions
diff --git a/absl/testing/tests/flagsaver_test.py b/absl/testing/tests/flagsaver_test.py
index e98cd06..b8f91a5 100644
--- a/absl/testing/tests/flagsaver_test.py
+++ b/absl/testing/tests/flagsaver_test.py
@@ -16,6 +16,7 @@
from absl import flags
from absl.testing import absltest
from absl.testing import flagsaver
+from absl.testing import parameterized
flags.DEFINE_string('flagsaver_test_flag0', 'unchanged0', 'flag to test with')
flags.DEFINE_string('flagsaver_test_flag1', 'unchanged1', 'flag to test with')
@@ -31,6 +32,9 @@ INT_FLAG = flags.DEFINE_integer(
STR_FLAG = flags.DEFINE_string(
'flagsaver_test_str_flag', default='str default', help='help')
+MULTI_INT_FLAG = flags.DEFINE_multi_integer('flagsaver_test_multi_int_flag',
+ None, 'flag to test with')
+
@flags.multi_flags_validator(
('flagsaver_test_validated_flag1', 'flagsaver_test_validated_flag2'))
@@ -51,194 +55,83 @@ class _TestError(Exception):
"""Exception class for use in these tests."""
-class FlagSaverTest(absltest.TestCase):
+class CommonUsageTest(absltest.TestCase):
+ """These test cases cover the most common usages of flagsaver."""
- def test_context_manager_without_parameters(self):
- with flagsaver.flagsaver():
- FLAGS.flagsaver_test_flag0 = 'new value'
- self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
-
- def test_context_manager_with_overrides(self):
- with flagsaver.flagsaver(flagsaver_test_flag0='new value'):
- self.assertEqual('new value', FLAGS.flagsaver_test_flag0)
- FLAGS.flagsaver_test_flag1 = 'another value'
+ def test_as_parsed_context_manager(self):
+ # Precondition check, we expect all the flags to start as their default.
+ self.assertEqual('str default', STR_FLAG.value)
+ self.assertFalse(STR_FLAG.present)
+ self.assertEqual(1, INT_FLAG.value)
self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
self.assertEqual('unchanged1', FLAGS.flagsaver_test_flag1)
- def test_context_manager_with_flagholders(self):
- with flagsaver.flagsaver((INT_FLAG, 3), (STR_FLAG, 'new value')):
- self.assertEqual('new value', STR_FLAG.value)
- self.assertEqual(3, INT_FLAG.value)
- FLAGS.flagsaver_test_flag1 = 'another value'
- self.assertEqual(INT_FLAG.value, INT_FLAG.default)
- self.assertEqual(STR_FLAG.value, STR_FLAG.default)
- self.assertEqual('unchanged1', FLAGS.flagsaver_test_flag1)
-
- def test_context_manager_with_overrides_and_flagholders(self):
- with flagsaver.flagsaver((INT_FLAG, 3), flagsaver_test_flag0='new value'):
- self.assertEqual(STR_FLAG.default, STR_FLAG.value)
- self.assertEqual(3, INT_FLAG.value)
- FLAGS.flagsaver_test_flag0 = 'new value'
- self.assertEqual(INT_FLAG.value, INT_FLAG.default)
- self.assertEqual(STR_FLAG.value, STR_FLAG.default)
- self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
-
- def test_context_manager_with_cross_validated_overrides_set_together(self):
- # When the flags are set in the same flagsaver call their validators will
- # be triggered only once the setting is done.
- with flagsaver.flagsaver(
- flagsaver_test_validated_flag1='new_value',
- flagsaver_test_validated_flag2='new_value'):
- self.assertEqual('new_value', FLAGS.flagsaver_test_validated_flag1)
- self.assertEqual('new_value', FLAGS.flagsaver_test_validated_flag2)
-
- self.assertIsNone(FLAGS.flagsaver_test_validated_flag1)
- self.assertIsNone(FLAGS.flagsaver_test_validated_flag2)
-
- def test_context_manager_with_cross_validated_overrides_set_badly(self):
-
- # Different values should violate the validator.
- with self.assertRaisesRegex(flags.IllegalFlagValueError,
- 'Flag validation failed'):
- with flagsaver.flagsaver(
- flagsaver_test_validated_flag1='new_value',
- flagsaver_test_validated_flag2='other_value'):
- pass
-
- self.assertIsNone(FLAGS.flagsaver_test_validated_flag1)
- self.assertIsNone(FLAGS.flagsaver_test_validated_flag2)
-
- def test_context_manager_with_cross_validated_overrides_set_separately(self):
-
- # Setting just one flag will trip the validator as well.
- with self.assertRaisesRegex(flags.IllegalFlagValueError,
- 'Flag validation failed'):
- with flagsaver.flagsaver(flagsaver_test_validated_flag1='new_value'):
- pass
-
- self.assertIsNone(FLAGS.flagsaver_test_validated_flag1)
- self.assertIsNone(FLAGS.flagsaver_test_validated_flag2)
-
- def test_context_manager_with_exception(self):
- with self.assertRaises(_TestError):
- with flagsaver.flagsaver(flagsaver_test_flag0='new value'):
- self.assertEqual('new value', FLAGS.flagsaver_test_flag0)
- FLAGS.flagsaver_test_flag1 = 'another value'
- raise _TestError('oops')
- self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
- self.assertEqual('unchanged1', FLAGS.flagsaver_test_flag1)
-
- def test_context_manager_with_validation_exception(self):
- with self.assertRaises(flags.IllegalFlagValueError):
- with flagsaver.flagsaver(
- flagsaver_test_flag0='new value',
- flagsaver_test_validated_flag='new value'):
- pass
- self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
- self.assertEqual('unchanged1', FLAGS.flagsaver_test_flag1)
- self.assertIsNone(FLAGS.flagsaver_test_validated_flag)
-
- def test_decorator_without_call(self):
-
- @flagsaver.flagsaver
- def mutate_flags(value):
- """Test function that mutates a flag."""
- # The undecorated method mutates --flagsaver_test_flag0 to the given value
- # and then returns the value of that flag. If the @flagsaver.flagsaver
- # decorator works as designed, then this mutation will be reverted after
- # this method returns.
- FLAGS.flagsaver_test_flag0 = value
- return FLAGS.flagsaver_test_flag0
-
- # mutate_flags returns the flag value before it gets restored by
- # the flagsaver decorator. So we check that flag value was
- # actually changed in the method's scope.
- self.assertEqual('new value', mutate_flags('new value'))
- # But... notice that the flag is now unchanged0.
- self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
-
- def test_decorator_without_parameters(self):
-
- @flagsaver.flagsaver()
- def mutate_flags(value):
- FLAGS.flagsaver_test_flag0 = value
- return FLAGS.flagsaver_test_flag0
-
- self.assertEqual('new value', mutate_flags('new value'))
- self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
-
- def test_decorator_with_overrides(self):
+ # Flagsaver will also save the state of flags that have been modified.
+ FLAGS.flagsaver_test_flag1 = 'outside flagsaver'
+
+ # Save all existing flag state, and set some flags as if they were parsed on
+ # the command line. Because of this, the new values must be provided as str,
+ # even if the flag type is something other than string.
+ with flagsaver.as_parsed(
+ (STR_FLAG, 'new string value'), # Override using flagholder object.
+ (INT_FLAG, '123'), # Override an int flag (NOTE: must specify as str).
+ flagsaver_test_flag0='new value', # Override using flag name.
+ ):
+ # All the flags have their overridden values.
+ self.assertEqual('new string value', STR_FLAG.value)
+ self.assertTrue(STR_FLAG.present)
+ self.assertEqual(123, INT_FLAG.value)
+ self.assertEqual('new value', FLAGS.flagsaver_test_flag0)
+ # Even if we change other flags, they will reset on context exit.
+ FLAGS.flagsaver_test_flag1 = 'new value 1'
- @flagsaver.flagsaver(flagsaver_test_flag0='new value')
- def mutate_flags():
- """Test function expecting new value."""
- # If the @flagsaver.decorator decorator works as designed,
- # then the value of the flag should be changed in the scope of
- # the method but the change will be reverted after this method
- # returns.
- return FLAGS.flagsaver_test_flag0
-
- # mutate_flags returns the flag value before it gets restored by
- # the flagsaver decorator. So we check that flag value was
- # actually changed in the method's scope.
- self.assertEqual('new value', mutate_flags())
- # But... notice that the flag is now unchanged0.
+ # The flags have all reset to their pre-flagsaver values.
+ self.assertEqual('str default', STR_FLAG.value)
+ self.assertFalse(STR_FLAG.present)
+ self.assertEqual(1, INT_FLAG.value)
self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
-
- def test_decorator_with_cross_validated_overrides_set_together(self):
-
- # When the flags are set in the same flagsaver call their validators will
- # be triggered only once the setting is done.
- @flagsaver.flagsaver(
- flagsaver_test_validated_flag1='new_value',
- flagsaver_test_validated_flag2='new_value')
- def mutate_flags_together():
- return (FLAGS.flagsaver_test_validated_flag1,
- FLAGS.flagsaver_test_validated_flag2)
-
- self.assertEqual(('new_value', 'new_value'), mutate_flags_together())
-
- # The flags have not changed outside the context of the function.
- self.assertIsNone(FLAGS.flagsaver_test_validated_flag1)
- self.assertIsNone(FLAGS.flagsaver_test_validated_flag2)
-
- def test_decorator_with_cross_validated_overrides_set_badly(self):
-
- # Different values should violate the validator.
- @flagsaver.flagsaver(
- flagsaver_test_validated_flag1='new_value',
- flagsaver_test_validated_flag2='other_value')
- def mutate_flags_together_badly():
- return (FLAGS.flagsaver_test_validated_flag1,
- FLAGS.flagsaver_test_validated_flag2)
-
- with self.assertRaisesRegex(flags.IllegalFlagValueError,
- 'Flag validation failed'):
- mutate_flags_together_badly()
-
- # The flags have not changed outside the context of the exception.
- self.assertIsNone(FLAGS.flagsaver_test_validated_flag1)
- self.assertIsNone(FLAGS.flagsaver_test_validated_flag2)
-
- def test_decorator_with_cross_validated_overrides_set_separately(self):
-
- # Setting the flags sequentially and not together will trip the validator,
- # because it will be called at the end of each flagsaver call.
- @flagsaver.flagsaver(flagsaver_test_validated_flag1='new_value')
- @flagsaver.flagsaver(flagsaver_test_validated_flag2='new_value')
- def mutate_flags_separately():
- return (FLAGS.flagsaver_test_validated_flag1,
- FLAGS.flagsaver_test_validated_flag2)
-
- with self.assertRaisesRegex(flags.IllegalFlagValueError,
- 'Flag validation failed'):
- mutate_flags_separately()
-
- # The flags have not changed outside the context of the exception.
- self.assertIsNone(FLAGS.flagsaver_test_validated_flag1)
- self.assertIsNone(FLAGS.flagsaver_test_validated_flag2)
-
- def test_save_flag_value(self):
+ self.assertEqual('outside flagsaver', FLAGS.flagsaver_test_flag1)
+
+ def test_as_parsed_decorator(self):
+ # flagsaver.as_parsed can also be used as a decorator.
+ @flagsaver.as_parsed((INT_FLAG, '123'))
+ def do_something_with_flags():
+ self.assertEqual(123, INT_FLAG.value)
+ self.assertTrue(INT_FLAG.present)
+
+ do_something_with_flags()
+ self.assertEqual(1, INT_FLAG.value)
+ self.assertFalse(INT_FLAG.present)
+
+ def test_flagsaver_flagsaver(self):
+ # If you don't want the flags to go through parsing, you can instead use
+ # flagsaver.flagsaver(). With this method, you provide the native python
+ # value you'd like the flags to take on. Otherwise it functions similar to
+ # flagsaver.as_parsed().
+ @flagsaver.flagsaver((INT_FLAG, 345))
+ def do_something_with_flags():
+ self.assertEqual(345, INT_FLAG.value)
+ # Note that because this flag was never parsed, it will not register as
+ # .present unless you manually set that attribute.
+ self.assertFalse(INT_FLAG.present)
+ # If you do chose to modify things about the flag (such as .present) those
+ # changes will still be cleaned up when flagsaver.flagsaver() exits.
+ INT_FLAG.present = True
+
+ self.assertEqual(1, INT_FLAG.value)
+ # flagsaver.flagsaver() restored INT_FLAG.present to the state it was in
+ # before entering the context.
+ self.assertFalse(INT_FLAG.present)
+
+
+class SaveFlagValuesTest(absltest.TestCase):
+ """Test flagsaver.save_flag_values() and flagsaver.restore_flag_values().
+
+ In this test, we insure that *all* properties of flags get restored. In other
+ tests we only try changing the flag value.
+ """
+
+ def test_assign_value(self):
# First save the flag values.
saved_flag_values = flagsaver.save_flag_values()
@@ -250,7 +143,7 @@ class FlagSaverTest(absltest.TestCase):
flagsaver.restore_flag_values(saved_flag_values)
self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
- def test_save_flag_default(self):
+ def test_set_default(self):
# First save the flag.
saved_flag_values = flagsaver.save_flag_values()
@@ -262,7 +155,7 @@ class FlagSaverTest(absltest.TestCase):
flagsaver.restore_flag_values(saved_flag_values)
self.assertEqual('unchanged0', FLAGS['flagsaver_test_flag0'].default)
- def test_restore_after_parse(self):
+ def test_parse(self):
# First save the flag.
saved_flag_values = flagsaver.save_flag_values()
@@ -278,9 +171,72 @@ class FlagSaverTest(absltest.TestCase):
self.assertEqual('unchanged0', FLAGS['flagsaver_test_flag0'].value)
self.assertEqual(0, FLAGS['flagsaver_test_flag0'].present)
- def test_decorator_with_exception(self):
+ def test_assign_validators(self):
+ # First save the flag.
+ saved_flag_values = flagsaver.save_flag_values()
+
+ # Sanity check that a validator already exists.
+ self.assertLen(FLAGS['flagsaver_test_flag0'].validators, 1)
+ original_validators = list(FLAGS['flagsaver_test_flag0'].validators)
+
+ def no_space(value):
+ return ' ' not in value
+
+ # Add a new validator.
+ flags.register_validator('flagsaver_test_flag0', no_space)
+ self.assertLen(FLAGS['flagsaver_test_flag0'].validators, 2)
+
+ # Now restore the flag to its original value.
+ flagsaver.restore_flag_values(saved_flag_values)
+ self.assertEqual(
+ original_validators, FLAGS['flagsaver_test_flag0'].validators
+ )
+
+
+@parameterized.named_parameters(
+ dict(
+ testcase_name='flagsaver.flagsaver',
+ flagsaver_method=flagsaver.flagsaver,
+ ),
+ dict(
+ testcase_name='flagsaver.as_parsed',
+ flagsaver_method=flagsaver.as_parsed,
+ ),
+)
+class NoOverridesTest(parameterized.TestCase):
+ """Test flagsaver.flagsaver and flagsaver.as_parsed without overrides."""
+
+ def test_context_manager_with_call(self, flagsaver_method):
+ with flagsaver_method():
+ FLAGS.flagsaver_test_flag0 = 'new value'
+ self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
+
+ def test_context_manager_with_exception(self, flagsaver_method):
+ with self.assertRaises(_TestError):
+ with flagsaver_method():
+ FLAGS.flagsaver_test_flag0 = 'new value'
+ # Simulate a failed test.
+ raise _TestError('something happened')
+ self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
+
+ def test_decorator_without_call(self, flagsaver_method):
+ @flagsaver_method
+ def mutate_flags():
+ FLAGS.flagsaver_test_flag0 = 'new value'
+
+ mutate_flags()
+ self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
+
+ def test_decorator_with_call(self, flagsaver_method):
+ @flagsaver_method()
+ def mutate_flags():
+ FLAGS.flagsaver_test_flag0 = 'new value'
- @flagsaver.flagsaver
+ mutate_flags()
+ self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
+
+ def test_decorator_with_exception(self, flagsaver_method):
+ @flagsaver_method()
def raise_exception():
FLAGS.flagsaver_test_flag0 = 'new value'
# Simulate a failed test.
@@ -290,62 +246,262 @@ class FlagSaverTest(absltest.TestCase):
self.assertRaises(_TestError, raise_exception)
self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
- def test_validator_list_is_restored(self):
- self.assertLen(FLAGS['flagsaver_test_flag0'].validators, 1)
- original_validators = list(FLAGS['flagsaver_test_flag0'].validators)
+@parameterized.named_parameters(
+ dict(
+ testcase_name='flagsaver.flagsaver',
+ flagsaver_method=flagsaver.flagsaver,
+ ),
+ dict(
+ testcase_name='flagsaver.as_parsed',
+ flagsaver_method=flagsaver.as_parsed,
+ ),
+)
+class TestStringFlagOverrides(parameterized.TestCase):
+ """Test flagsaver.flagsaver and flagsaver.as_parsed with string overrides.
+
+ Note that these tests can be parameterized because both .flagsaver and
+ .as_parsed expect a str input when overriding a string flag. For non-string
+ flags these two flagsaver methods have separate tests elsewhere in this file.
+
+ Each test is one class of overrides, executed twice. Once as a context
+ manager, and once as a decorator on a mutate_flags() method.
+ """
+
+ def test_keyword_overrides(self, flagsaver_method):
+ # Context manager:
+ with flagsaver_method(flagsaver_test_flag0='new value'):
+ self.assertEqual('new value', FLAGS.flagsaver_test_flag0)
+ self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
- @flagsaver.flagsaver
- def modify_validators():
+ # Decorator:
+ @flagsaver_method(flagsaver_test_flag0='new value')
+ def mutate_flags():
+ self.assertEqual('new value', FLAGS.flagsaver_test_flag0)
- def no_space(value):
- return ' ' not in value
+ mutate_flags()
+ self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
- flags.register_validator('flagsaver_test_flag0', no_space)
- self.assertLen(FLAGS['flagsaver_test_flag0'].validators, 2)
+ def test_flagholder_overrides(self, flagsaver_method):
+ with flagsaver_method((STR_FLAG, 'new value')):
+ self.assertEqual('new value', STR_FLAG.value)
+ self.assertEqual('str default', STR_FLAG.value)
- modify_validators()
- self.assertEqual(original_validators,
- FLAGS['flagsaver_test_flag0'].validators)
+ @flagsaver_method((STR_FLAG, 'new value'))
+ def mutate_flags():
+ self.assertEqual('new value', STR_FLAG.value)
+ mutate_flags()
+ self.assertEqual('str default', STR_FLAG.value)
-class FlagSaverDecoratorUsageTest(absltest.TestCase):
+ def test_keyword_and_flagholder_overrides(self, flagsaver_method):
+ with flagsaver_method(
+ (STR_FLAG, 'another value'), flagsaver_test_flag0='new value'
+ ):
+ self.assertEqual('another value', STR_FLAG.value)
+ self.assertEqual('new value', FLAGS.flagsaver_test_flag0)
+ self.assertEqual('str default', STR_FLAG.value)
+ self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
- @flagsaver.flagsaver
- def test_mutate1(self):
- # Even though other test cases change the flag, it should be
- # restored to 'unchanged0' if the flagsaver is working.
+ @flagsaver_method(
+ (STR_FLAG, 'another value'), flagsaver_test_flag0='new value'
+ )
+ def mutate_flags():
+ self.assertEqual('another value', STR_FLAG.value)
+ self.assertEqual('new value', FLAGS.flagsaver_test_flag0)
+
+ mutate_flags()
+ self.assertEqual('str default', STR_FLAG.value)
self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
- FLAGS.flagsaver_test_flag0 = 'changed0'
- @flagsaver.flagsaver
- def test_mutate2(self):
- # Even though other test cases change the flag, it should be
- # restored to 'unchanged0' if the flagsaver is working.
+ def test_cross_validated_overrides_set_together(self, flagsaver_method):
+ # When the flags are set in the same flagsaver call their validators will
+ # be triggered only once the setting is done.
+ with flagsaver_method(
+ flagsaver_test_validated_flag1='new_value',
+ flagsaver_test_validated_flag2='new_value',
+ ):
+ self.assertEqual('new_value', FLAGS.flagsaver_test_validated_flag1)
+ self.assertEqual('new_value', FLAGS.flagsaver_test_validated_flag2)
+ self.assertIsNone(FLAGS.flagsaver_test_validated_flag1)
+ self.assertIsNone(FLAGS.flagsaver_test_validated_flag2)
+
+ @flagsaver_method(
+ flagsaver_test_validated_flag1='new_value',
+ flagsaver_test_validated_flag2='new_value',
+ )
+ def mutate_flags():
+ self.assertEqual('new_value', FLAGS.flagsaver_test_validated_flag1)
+ self.assertEqual('new_value', FLAGS.flagsaver_test_validated_flag2)
+
+ mutate_flags()
+ self.assertIsNone(FLAGS.flagsaver_test_validated_flag1)
+ self.assertIsNone(FLAGS.flagsaver_test_validated_flag2)
+
+ def test_cross_validated_overrides_set_badly(self, flagsaver_method):
+ # Different values should violate the validator.
+ with self.assertRaisesRegex(
+ flags.IllegalFlagValueError, 'Flag validation failed'
+ ):
+ with flagsaver_method(
+ flagsaver_test_validated_flag1='new_value',
+ flagsaver_test_validated_flag2='other_value',
+ ):
+ pass
+ self.assertIsNone(FLAGS.flagsaver_test_validated_flag1)
+ self.assertIsNone(FLAGS.flagsaver_test_validated_flag2)
+
+ @flagsaver_method(
+ flagsaver_test_validated_flag1='new_value',
+ flagsaver_test_validated_flag2='other_value',
+ )
+ def mutate_flags():
+ pass
+
+ self.assertRaisesRegex(
+ flags.IllegalFlagValueError, 'Flag validation failed', mutate_flags
+ )
+ self.assertIsNone(FLAGS.flagsaver_test_validated_flag1)
+ self.assertIsNone(FLAGS.flagsaver_test_validated_flag2)
+
+ def test_cross_validated_overrides_set_separately(self, flagsaver_method):
+ # Setting just one flag will trip the validator as well.
+ with self.assertRaisesRegex(
+ flags.IllegalFlagValueError, 'Flag validation failed'
+ ):
+ with flagsaver_method(flagsaver_test_validated_flag1='new_value'):
+ pass
+ self.assertIsNone(FLAGS.flagsaver_test_validated_flag1)
+ self.assertIsNone(FLAGS.flagsaver_test_validated_flag2)
+
+ @flagsaver_method(flagsaver_test_validated_flag1='new_value')
+ def mutate_flags():
+ pass
+
+ self.assertRaisesRegex(
+ flags.IllegalFlagValueError, 'Flag validation failed', mutate_flags
+ )
+ self.assertIsNone(FLAGS.flagsaver_test_validated_flag1)
+ self.assertIsNone(FLAGS.flagsaver_test_validated_flag2)
+
+ def test_validation_exception(self, flagsaver_method):
+ with self.assertRaises(flags.IllegalFlagValueError):
+ with flagsaver_method(
+ flagsaver_test_flag0='new value',
+ flagsaver_test_validated_flag='new value',
+ ):
+ pass
self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
- FLAGS.flagsaver_test_flag0 = 'changed0'
+ self.assertIsNone(FLAGS.flagsaver_test_validated_flag)
- @flagsaver.flagsaver
- def test_mutate3(self):
- # Even though other test cases change the flag, it should be
- # restored to 'unchanged0' if the flagsaver is working.
+ @flagsaver_method(
+ flagsaver_test_flag0='new value',
+ flagsaver_test_validated_flag='new value',
+ )
+ def mutate_flags():
+ pass
+
+ self.assertRaises(flags.IllegalFlagValueError, mutate_flags)
self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
- FLAGS.flagsaver_test_flag0 = 'changed0'
+ self.assertIsNone(FLAGS.flagsaver_test_validated_flag)
- @flagsaver.flagsaver
- def test_mutate4(self):
- # Even though other test cases change the flag, it should be
- # restored to 'unchanged0' if the flagsaver is working.
+ def test_unknown_flag_raises_exception(self, flagsaver_method):
+ self.assertNotIn('this_flag_does_not_exist', FLAGS)
+
+ # Flagsaver raises an error when trying to override a non-existent flag.
+ with self.assertRaises(flags.UnrecognizedFlagError):
+ with flagsaver_method(
+ flagsaver_test_flag0='new value', this_flag_does_not_exist='new value'
+ ):
+ pass
self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
- FLAGS.flagsaver_test_flag0 = 'changed0'
+ @flagsaver_method(
+ flagsaver_test_flag0='new value', this_flag_does_not_exist='new value'
+ )
+ def mutate_flags():
+ pass
+
+ self.assertRaises(flags.UnrecognizedFlagError, mutate_flags)
+ self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
-class FlagSaverSetUpTearDownUsageTest(absltest.TestCase):
+ # Make sure flagsaver didn't create the flag at any point.
+ self.assertNotIn('this_flag_does_not_exist', FLAGS)
+
+
+class AsParsedTest(absltest.TestCase):
+
+ def test_parse_context_manager_sets_present_and_using_default(self):
+ self.assertFalse(INT_FLAG.present)
+ self.assertFalse(STR_FLAG.present)
+ # Note that .using_default_value isn't available on the FlagHolder directly.
+ self.assertTrue(FLAGS[INT_FLAG.name].using_default_value)
+ self.assertTrue(FLAGS[STR_FLAG.name].using_default_value)
+
+ with flagsaver.as_parsed((INT_FLAG, '123'),
+ flagsaver_test_str_flag='new value'):
+ self.assertTrue(INT_FLAG.present)
+ self.assertTrue(STR_FLAG.present)
+ self.assertFalse(FLAGS[INT_FLAG.name].using_default_value)
+ self.assertFalse(FLAGS[STR_FLAG.name].using_default_value)
+
+ self.assertFalse(INT_FLAG.present)
+ self.assertFalse(STR_FLAG.present)
+ self.assertTrue(FLAGS[INT_FLAG.name].using_default_value)
+ self.assertTrue(FLAGS[STR_FLAG.name].using_default_value)
+
+ def test_parse_decorator_sets_present_and_using_default(self):
+ self.assertFalse(INT_FLAG.present)
+ self.assertFalse(STR_FLAG.present)
+ # Note that .using_default_value isn't available on the FlagHolder directly.
+ self.assertTrue(FLAGS[INT_FLAG.name].using_default_value)
+ self.assertTrue(FLAGS[STR_FLAG.name].using_default_value)
+
+ @flagsaver.as_parsed((INT_FLAG, '123'), flagsaver_test_str_flag='new value')
+ def some_func():
+ self.assertTrue(INT_FLAG.present)
+ self.assertTrue(STR_FLAG.present)
+ self.assertFalse(FLAGS[INT_FLAG.name].using_default_value)
+ self.assertFalse(FLAGS[STR_FLAG.name].using_default_value)
+
+ some_func()
+ self.assertFalse(INT_FLAG.present)
+ self.assertFalse(STR_FLAG.present)
+ self.assertTrue(FLAGS[INT_FLAG.name].using_default_value)
+ self.assertTrue(FLAGS[STR_FLAG.name].using_default_value)
+
+ def test_parse_decorator_with_multi_int_flag(self):
+ self.assertFalse(MULTI_INT_FLAG.present)
+ self.assertIsNone(MULTI_INT_FLAG.value)
+
+ @flagsaver.as_parsed((MULTI_INT_FLAG, ['123', '456']))
+ def assert_flags_updated():
+ self.assertTrue(MULTI_INT_FLAG.present)
+ self.assertCountEqual([123, 456], MULTI_INT_FLAG.value)
+
+ assert_flags_updated()
+ self.assertFalse(MULTI_INT_FLAG.present)
+ self.assertIsNone(MULTI_INT_FLAG.value)
+
+ def test_parse_raises_type_error(self):
+ with self.assertRaisesRegex(
+ TypeError,
+ r'flagsaver\.as_parsed\(\) cannot parse flagsaver_test_int_flag\. '
+ r'Expected a single string or sequence of strings but .*int.* was '
+ r'provided\.'):
+ manager = flagsaver.as_parsed(flagsaver_test_int_flag=123)
+ del manager
+
+
+class SetUpTearDownTest(absltest.TestCase):
+ """Example using a single flagsaver in setUp."""
def setUp(self):
+ super().setUp()
self.saved_flag_values = flagsaver.save_flag_values()
def tearDown(self):
+ super().tearDown()
flagsaver.restore_flag_values(self.saved_flag_values)
def test_mutate1(self):
@@ -360,28 +516,26 @@ class FlagSaverSetUpTearDownUsageTest(absltest.TestCase):
self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
FLAGS.flagsaver_test_flag0 = 'changed0'
- def test_mutate3(self):
- # Even though other test cases change the flag, it should be
- # restored to 'unchanged0' if the flagsaver is working.
- self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
- FLAGS.flagsaver_test_flag0 = 'changed0'
-
- def test_mutate4(self):
- # Even though other test cases change the flag, it should be
- # restored to 'unchanged0' if the flagsaver is working.
- self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
- FLAGS.flagsaver_test_flag0 = 'changed0'
-
-class FlagSaverBadUsageTest(absltest.TestCase):
- """Tests that certain kinds of improper usages raise errors."""
-
- def test_flag_saver_on_class(self):
+@parameterized.named_parameters(
+ dict(
+ testcase_name='flagsaver.flagsaver',
+ flagsaver_method=flagsaver.flagsaver,
+ ),
+ dict(
+ testcase_name='flagsaver.as_parsed',
+ flagsaver_method=flagsaver.as_parsed,
+ ),
+)
+class BadUsageTest(parameterized.TestCase):
+ """Tests that improper usage (such as decorating a class) raise errors."""
+
+ def test_flag_saver_on_class(self, flagsaver_method):
with self.assertRaises(TypeError):
# WRONG. Don't do this.
# Consider the correct usage example in FlagSaverSetUpTearDownUsageTest.
- @flagsaver.flagsaver
+ @flagsaver_method
class FooTest(absltest.TestCase):
def test_tautology(self):
@@ -389,12 +543,12 @@ class FlagSaverBadUsageTest(absltest.TestCase):
del FooTest
- def test_flag_saver_call_on_class(self):
+ def test_flag_saver_call_on_class(self, flagsaver_method):
with self.assertRaises(TypeError):
# WRONG. Don't do this.
# Consider the correct usage example in FlagSaverSetUpTearDownUsageTest.
- @flagsaver.flagsaver()
+ @flagsaver_method()
class FooTest(absltest.TestCase):
def test_tautology(self):
@@ -402,12 +556,12 @@ class FlagSaverBadUsageTest(absltest.TestCase):
del FooTest
- def test_flag_saver_with_overrides_on_class(self):
+ def test_flag_saver_with_overrides_on_class(self, flagsaver_method):
with self.assertRaises(TypeError):
# WRONG. Don't do this.
# Consider the correct usage example in FlagSaverSetUpTearDownUsageTest.
- @flagsaver.flagsaver(foo='bar')
+ @flagsaver_method(foo='bar')
class FooTest(absltest.TestCase):
def test_tautology(self):
@@ -415,48 +569,57 @@ class FlagSaverBadUsageTest(absltest.TestCase):
del FooTest
- def test_multiple_positional_parameters(self):
+ def test_multiple_positional_parameters(self, flagsaver_method):
with self.assertRaises(ValueError):
func_a = lambda: None
func_b = lambda: None
- flagsaver.flagsaver(func_a, func_b)
+ flagsaver_method(func_a, func_b)
- def test_both_positional_and_keyword_parameters(self):
+ def test_both_positional_and_keyword_parameters(self, flagsaver_method):
with self.assertRaises(ValueError):
func_a = lambda: None
- flagsaver.flagsaver(func_a, flagsaver_test_flag0='new value')
+ flagsaver_method(func_a, flagsaver_test_flag0='new value')
- def test_duplicate_holder_parameters(self):
+ def test_duplicate_holder_parameters(self, flagsaver_method):
with self.assertRaises(ValueError):
- flagsaver.flagsaver((INT_FLAG, 45), (INT_FLAG, 45))
+ flagsaver_method((INT_FLAG, 45), (INT_FLAG, 45))
- def test_duplicate_holder_and_kw_parameter(self):
+ def test_duplicate_holder_and_kw_parameter(self, flagsaver_method):
with self.assertRaises(ValueError):
- flagsaver.flagsaver((INT_FLAG, 45), **{INT_FLAG.name: 45})
+ flagsaver_method((INT_FLAG, 45), **{INT_FLAG.name: 45})
- def test_both_positional_and_holder_parameters(self):
+ def test_both_positional_and_holder_parameters(self, flagsaver_method):
with self.assertRaises(ValueError):
func_a = lambda: None
- flagsaver.flagsaver(func_a, (INT_FLAG, 45))
+ flagsaver_method(func_a, (INT_FLAG, 45))
- def test_holder_parameters_wrong_shape(self):
+ def test_holder_parameters_wrong_shape(self, flagsaver_method):
with self.assertRaises(ValueError):
- flagsaver.flagsaver(INT_FLAG)
+ flagsaver_method(INT_FLAG)
- def test_holder_parameters_tuple_too_long(self):
+ def test_holder_parameters_tuple_too_long(self, flagsaver_method):
with self.assertRaises(ValueError):
# Even if it is a bool flag, it should be a tuple
- flagsaver.flagsaver((INT_FLAG, 4, 5))
+ flagsaver_method((INT_FLAG, 4, 5))
- def test_holder_parameters_tuple_wrong_type(self):
+ def test_holder_parameters_tuple_wrong_type(self, flagsaver_method):
with self.assertRaises(ValueError):
# Even if it is a bool flag, it should be a tuple
- flagsaver.flagsaver((4, INT_FLAG))
+ flagsaver_method((4, INT_FLAG))
- def test_both_wrong_positional_parameters(self):
+ def test_both_wrong_positional_parameters(self, flagsaver_method):
with self.assertRaises(ValueError):
func_a = lambda: None
- flagsaver.flagsaver(func_a, STR_FLAG, '45')
+ flagsaver_method(func_a, STR_FLAG, '45')
+
+ def test_context_manager_no_call(self, flagsaver_method):
+ # The exact exception that's raised appears to be system specific.
+ with self.assertRaises((AttributeError, TypeError)):
+ # Wrong. You must call the flagsaver method before using it as a CM.
+ with flagsaver_method:
+ # We don't expect to get here. A type error should happen when
+ # attempting to enter the context manager.
+ pass
if __name__ == '__main__':