diff options
author | Yilei Yang <yileiyang@google.com> | 2022-07-14 15:59:50 -0700 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2022-07-14 16:00:17 -0700 |
commit | f2a901edd64b8e863d3e1dfb3df4b7c91cf5507f (patch) | |
tree | 8dce130fc109495307ee065c5f4c4332a89de293 | |
parent | fea82554c370d78e9c9eb63e0d8cc85cac30ff15 (diff) | |
download | absl-py-f2a901edd64b8e863d3e1dfb3df4b7c91cf5507f.tar.gz |
Make `TempFileCleanup.SUCCESS` work with Python 3.11 after https://github.com/python/cpython/pull/28180.
After the change, the errors from the test case were no longer buffered in `_Outcome`. Instead, we need to take a note of errors on the `TestResult` before, then compare errors after.
PiperOrigin-RevId: 461070558
Change-Id: I7d9f769cd46143a886bc5edeb224804acd8dbaf9
-rw-r--r-- | CHANGELOG.md | 4 | ||||
-rw-r--r-- | absl/testing/absltest.py | 43 | ||||
-rw-r--r-- | absl/testing/tests/absltest_test.py | 19 | ||||
-rw-r--r-- | absl/testing/tests/absltest_test_helper.py | 16 |
4 files changed, 70 insertions, 12 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c36751..d083f61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com). ## Unreleased -Nothing notable unreleased. +### Fixed + +* Fixed a crash in Python 3.11 when `TempFileCleanup.SUCCESS` is used. ## 1.1.0 (2022-06-01) diff --git a/absl/testing/absltest.py b/absl/testing/absltest.py index d3cf95a..b7a941b 100644 --- a/absl/testing/absltest.py +++ b/absl/testing/absltest.py @@ -787,24 +787,49 @@ class TestCase(unittest.TestCase): elif cleanup == TempFileCleanup.ALWAYS: self.addCleanup(_rmtree_ignore_errors, path) elif cleanup == TempFileCleanup.SUCCESS: - self._internal_cleanup_on_success(_rmtree_ignore_errors, path) + self._internal_add_cleanup_on_success(_rmtree_ignore_errors, path) else: raise AssertionError('Unexpected cleanup value: {}'.format(cleanup)) - def _internal_cleanup_on_success(self, function, *args, **kwargs): - # type: (Callable[..., object], Any, Any) -> None + def _internal_add_cleanup_on_success( + self, + function: Callable[..., Any], + *args: Any, + **kwargs: Any, + ) -> None: + """Adds `function` as cleanup when the test case succeeds.""" + outcome = self._outcome + previous_failure_count = ( + len(outcome.result.failures) + + len(outcome.result.errors) + + len(outcome.result.unexpectedSuccesses) + ) def _call_cleaner_on_success(*args, **kwargs): - if not self._ran_and_passed(): + if not self._internal_ran_and_passed_when_called_during_cleanup( + previous_failure_count): return function(*args, **kwargs) self.addCleanup(_call_cleaner_on_success, *args, **kwargs) - def _ran_and_passed(self): - # type: () -> bool + def _internal_ran_and_passed_when_called_during_cleanup( + self, + previous_failure_count: int, + ) -> bool: + """Returns whether test is passed. Expected to be called during cleanup.""" outcome = self._outcome - result = self.defaultTestResult() - self._feedErrorsToResult(result, outcome.errors) # pytype: disable=attribute-error - return result.wasSuccessful() + if sys.version_info[:2] >= (3, 11): + current_failure_count = ( + len(outcome.result.failures) + + len(outcome.result.errors) + + len(outcome.result.unexpectedSuccesses) + ) + return current_failure_count == previous_failure_count + else: + # Before Python 3.11 https://github.com/python/cpython/pull/28180, errors + # were bufferred in _Outcome before calling cleanup. + result = self.defaultTestResult() + self._feedErrorsToResult(result, outcome.errors) # pytype: disable=attribute-error + return result.wasSuccessful() def shortDescription(self): # type: () -> Text diff --git a/absl/testing/tests/absltest_test.py b/absl/testing/tests/absltest_test.py index d941e07..43201bd 100644 --- a/absl/testing/tests/absltest_test.py +++ b/absl/testing/tests/absltest_test.py @@ -2145,6 +2145,11 @@ class TempFileTest(absltest.TestCase, HelperMixin): 'TempFileHelperTest/test_failure', 'TempFileHelperTest/test_failure/failure', 'TempFileHelperTest/test_success', + 'TempFileHelperTest/test_subtest_failure', + 'TempFileHelperTest/test_subtest_failure/parent', + 'TempFileHelperTest/test_subtest_failure/successful_child', + 'TempFileHelperTest/test_subtest_failure/failed_child', + 'TempFileHelperTest/test_subtest_success', } self.run_tempfile_helper('SUCCESS', expected) @@ -2153,6 +2158,8 @@ class TempFileTest(absltest.TestCase, HelperMixin): 'TempFileHelperTest', 'TempFileHelperTest/test_failure', 'TempFileHelperTest/test_success', + 'TempFileHelperTest/test_subtest_failure', + 'TempFileHelperTest/test_subtest_success', } self.run_tempfile_helper('ALWAYS', expected) @@ -2163,6 +2170,14 @@ class TempFileTest(absltest.TestCase, HelperMixin): 'TempFileHelperTest/test_failure/failure', 'TempFileHelperTest/test_success', 'TempFileHelperTest/test_success/success', + 'TempFileHelperTest/test_subtest_failure', + 'TempFileHelperTest/test_subtest_failure/parent', + 'TempFileHelperTest/test_subtest_failure/successful_child', + 'TempFileHelperTest/test_subtest_failure/failed_child', + 'TempFileHelperTest/test_subtest_success', + 'TempFileHelperTest/test_subtest_success/parent', + 'TempFileHelperTest/test_subtest_success/child0', + 'TempFileHelperTest/test_subtest_success/child1', } self.run_tempfile_helper('OFF', expected) @@ -2172,8 +2187,8 @@ class SkipClassTest(absltest.TestCase): def test_incorrect_decorator_call(self): with self.assertRaises(TypeError): - @absltest.skipThisClass # pylint: disable=unused-variable - class Test(absltest.TestCase): + @absltest.skipThisClass + class Test(absltest.TestCase): # pylint: disable=unused-variable pass def test_incorrect_decorator_subclass(self): diff --git a/absl/testing/tests/absltest_test_helper.py b/absl/testing/tests/absltest_test_helper.py index e81a89b..89b6721 100644 --- a/absl/testing/tests/absltest_test_helper.py +++ b/absl/testing/tests/absltest_test_helper.py @@ -106,6 +106,8 @@ class HelperTest(absltest.TestCase): class TempFileHelperTest(absltest.TestCase): + """Helper test case for tempfile cleanup tests.""" + tempfile_cleanup = absltest.TempFileCleanup[os.environ.get( 'ABSLTEST_TEST_HELPER_TEMPFILE_CLEANUP', 'SUCCESS')] @@ -116,6 +118,20 @@ class TempFileHelperTest(absltest.TestCase): def test_success(self): self.create_tempfile('success') + def test_subtest_failure(self): + self.create_tempfile('parent') + with self.subTest('success'): + self.create_tempfile('successful_child') + with self.subTest('failure'): + self.create_tempfile('failed_child') + self.fail('expected failure') + + def test_subtest_success(self): + self.create_tempfile('parent') + for i in range(2): + with self.subTest(f'success{i}'): + self.create_tempfile(f'child{i}') + def main(argv): del argv # Unused. |