Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add recordProperty and getRecordedProperties. #298

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions absl/testing/absltest.py
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,10 @@ def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
# This is to work around missing type stubs in unittest.pyi
self._outcome: Optional[Any] = getattr(self, '_outcome')
# A dict[str, Any] of properties for the test itself.
self.__recorded_properties = {}
# A dict of properties dicts per subtest, keyed by the subtest's id().
self.__subtest_properties = collections.defaultdict(dict)

def setUp(self):
super().setUp()
Expand All @@ -604,6 +608,47 @@ def setUpClass(cls):
cls._cls_exit_stack = contextlib.ExitStack()
cls.addClassCleanup(cls._cls_exit_stack.close)

def getRecordedProperties(self, subtest=None):
"""Returns any properties that the user has recorded.

If called from within a subtest and subtest is None, returns a dict made up
of *both* the subtest's properties *and* the outer test's properties. (The
subtest's properties take precedence in the event of a conflict.)

Args:
subtest: the subtest whose properties should be returned (default: None)
Unlike the default case, if subtest is set, *only* that subtest's
properties are returned, not those of the enclosing test.
"""
if subtest:
# Return *only* subtest properties
return self.__subtest_properties[subtest.id()].copy()
ret = self.__recorded_properties.copy()
if hasattr(self, '_subtest') and self._subtest:
ret |= self.__subtest_properties[self._subtest.id()]
return ret

def recordProperty(self, property_name, property_value):
"""Record an arbitrary property for later use.

The property is attributed to the currently active subtest, if any,
or the test itself, otherwise.

Args:
property_name: str, name of property to record; must be a valid XML
attribute name.
property_value: value of property; must be valid XML attribute value.
"""
# The following avoids breakage due to a two-arg call to
# getRecordedProperties in subclasses of absltest.TestCase that override it
# with the legacy one-arg signature but don't override recordProperty, so
# long as tests based on those subclasses have no subTests.
if hasattr(self, '_subtest') and self._subtest:
recorded_properties = self.__subtest_properties[self._subtest.id()]
else:
recorded_properties = self.__recorded_properties
recorded_properties[property_name] = property_value

def create_tempdir(
self,
name: Optional[str] = None,
Expand Down
44 changes: 44 additions & 0 deletions absl/testing/tests/absltest_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,50 @@ def test_flags_env_var_flags(self):
expect_success=True,
)

def testRecordedProperties(self):
"""Tests that a test can record a property and then retrieve it."""
self.recordProperty('test_property', 'test_value')
self.assertEqual(
self.getRecordedProperties(), {'test_property': 'test_value'}
)

def testRecordedPropertiesSubTest(self):
"""Tests that a test can record a subtest's property and retrieve it."""
self.recordProperty('test_property1', 'test_value1')
subtest1 = None
with self.subTest(name='sub1'):
assert hasattr(self, '_subtest')
subtest1 = self._subtest
self.assertIsNotNone(subtest1)
self.recordProperty('subtest_property', 'sub_value1')
self.assertEqual(
self.getRecordedProperties(),
{'test_property1': 'test_value1', 'subtest_property': 'sub_value1'},
)
subtest2 = None
with self.subTest(name='sub2'):
assert hasattr(self, '_subtest')
subtest2 = self._subtest
self.assertIsNotNone(subtest2)
self.recordProperty('subtest_property', 'sub_value2')
self.assertEqual(
self.getRecordedProperties(),
{'test_property1': 'test_value1', 'subtest_property': 'sub_value2'},
)
self.recordProperty('test_property2', 'test_value2')
self.assertEqual(
self.getRecordedProperties(),
{'test_property1': 'test_value1', 'test_property2': 'test_value2'},
)
# Verify that subtest1 and subtest2 have different dict entries and don't
# overwrite each others' values.
self.assertEqual(
self.getRecordedProperties(subtest1), {'subtest_property': 'sub_value1'}
)
self.assertEqual(
self.getRecordedProperties(subtest2), {'subtest_property': 'sub_value2'}
)

def test_xml_output_file_from_xml_output_file_env(self):
xml_dir = tempfile.mkdtemp(dir=absltest.TEST_TMPDIR.value)
xml_output_file_env = os.path.join(xml_dir, 'xml_output_file.xml')
Expand Down
Loading