Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc06caac

Browse files
gh-134565: Use ExceptionGroup to handle multiple errors in unittest.doModuleCleanup()
1 parent366d95d commitc06caac

File tree

5 files changed

+89
-10
lines changed

5 files changed

+89
-10
lines changed

‎Lib/test/test_unittest/test_result.py

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1282,14 +1282,22 @@ def setUpModule():
12821282
suite(result)
12831283
expected_out='\nStdout:\ndo cleanup2\ndo cleanup1\n'
12841284
self.assertEqual(stdout.getvalue(),expected_out)
1285-
self.assertEqual(len(result.errors),1)
1285+
self.assertEqual(len(result.errors),2)
12861286
description='tearDownModule (Module)'
12871287
test_case,formatted_exc=result.errors[0]
12881288
self.assertEqual(test_case.description,description)
12891289
self.assertIn('ValueError: bad cleanup2',formatted_exc)
1290+
self.assertNotIn('ExceptionGroup',formatted_exc)
12901291
self.assertNotIn('TypeError',formatted_exc)
12911292
self.assertIn(expected_out,formatted_exc)
12921293

1294+
test_case,formatted_exc=result.errors[1]
1295+
self.assertEqual(test_case.description,description)
1296+
self.assertIn('TypeError: bad cleanup1',formatted_exc)
1297+
self.assertNotIn('ExceptionGroup',formatted_exc)
1298+
self.assertNotIn('ValueError',formatted_exc)
1299+
self.assertIn(expected_out,formatted_exc)
1300+
12931301
deftestBufferSetUpModule_DoModuleCleanups(self):
12941302
withcaptured_stdout()asstdout:
12951303
result=unittest.TestResult()
@@ -1313,22 +1321,34 @@ def setUpModule():
13131321
suite(result)
13141322
expected_out='\nStdout:\nset up module\ndo cleanup2\ndo cleanup1\n'
13151323
self.assertEqual(stdout.getvalue(),expected_out)
1316-
self.assertEqual(len(result.errors),2)
1324+
self.assertEqual(len(result.errors),3)
13171325
description='setUpModule (Module)'
13181326
test_case,formatted_exc=result.errors[0]
13191327
self.assertEqual(test_case.description,description)
13201328
self.assertIn('ZeroDivisionError: division by zero',formatted_exc)
1329+
self.assertNotIn('ExceptionGroup',formatted_exc)
13211330
self.assertNotIn('ValueError',formatted_exc)
13221331
self.assertNotIn('TypeError',formatted_exc)
13231332
self.assertIn('\nStdout:\nset up module\n',formatted_exc)
1333+
13241334
test_case,formatted_exc=result.errors[1]
13251335
self.assertIn(expected_out,formatted_exc)
13261336
self.assertEqual(test_case.description,description)
13271337
self.assertIn('ValueError: bad cleanup2',formatted_exc)
1338+
self.assertNotIn('ExceptionGroup',formatted_exc)
13281339
self.assertNotIn('ZeroDivisionError',formatted_exc)
13291340
self.assertNotIn('TypeError',formatted_exc)
13301341
self.assertIn(expected_out,formatted_exc)
13311342

1343+
test_case,formatted_exc=result.errors[2]
1344+
self.assertIn(expected_out,formatted_exc)
1345+
self.assertEqual(test_case.description,description)
1346+
self.assertIn('TypeError: bad cleanup1',formatted_exc)
1347+
self.assertNotIn('ExceptionGroup',formatted_exc)
1348+
self.assertNotIn('ZeroDivisionError',formatted_exc)
1349+
self.assertNotIn('ValueError',formatted_exc)
1350+
self.assertIn(expected_out,formatted_exc)
1351+
13321352
deftestBufferTearDownModule_DoModuleCleanups(self):
13331353
withcaptured_stdout()asstdout:
13341354
result=unittest.TestResult()
@@ -1355,21 +1375,32 @@ def tearDownModule():
13551375
suite(result)
13561376
expected_out='\nStdout:\ntear down module\ndo cleanup2\ndo cleanup1\n'
13571377
self.assertEqual(stdout.getvalue(),expected_out)
1358-
self.assertEqual(len(result.errors),2)
1378+
self.assertEqual(len(result.errors),3)
13591379
description='tearDownModule (Module)'
13601380
test_case,formatted_exc=result.errors[0]
13611381
self.assertEqual(test_case.description,description)
13621382
self.assertIn('ZeroDivisionError: division by zero',formatted_exc)
1383+
self.assertNotIn('ExceptionGroup',formatted_exc)
13631384
self.assertNotIn('ValueError',formatted_exc)
13641385
self.assertNotIn('TypeError',formatted_exc)
13651386
self.assertIn('\nStdout:\ntear down module\n',formatted_exc)
1387+
13661388
test_case,formatted_exc=result.errors[1]
13671389
self.assertEqual(test_case.description,description)
13681390
self.assertIn('ValueError: bad cleanup2',formatted_exc)
1391+
self.assertNotIn('ExceptionGroup',formatted_exc)
13691392
self.assertNotIn('ZeroDivisionError',formatted_exc)
13701393
self.assertNotIn('TypeError',formatted_exc)
13711394
self.assertIn(expected_out,formatted_exc)
13721395

1396+
test_case,formatted_exc=result.errors[2]
1397+
self.assertEqual(test_case.description,description)
1398+
self.assertIn('TypeError: bad cleanup1',formatted_exc)
1399+
self.assertNotIn('ExceptionGroup',formatted_exc)
1400+
self.assertNotIn('ZeroDivisionError',formatted_exc)
1401+
self.assertNotIn('ValueError',formatted_exc)
1402+
self.assertIn(expected_out,formatted_exc)
1403+
13731404

13741405
if__name__=='__main__':
13751406
unittest.main()

‎Lib/test/test_unittest/test_runner.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,39 @@ class Module(object):
651651
self.assertEqual(str(e.exception),'CleanUpExc')
652652
self.assertEqual(unittest.case._module_cleanups, [])
653653

654+
deftest_doModuleCleanup_with_multiple_errors_in_addModuleCleanup(self):
655+
defmodule_cleanup_bad1():
656+
raiseTypeError('CleanUpExc1')
657+
658+
defmodule_cleanup_bad2():
659+
raiseValueError('CleanUpExc2')
660+
661+
classModule(object):
662+
unittest.addModuleCleanup(module_cleanup_bad1)
663+
unittest.addModuleCleanup(module_cleanup_bad2)
664+
withself.assertRaises(ExceptionGroup)ase:
665+
unittest.case.doModuleCleanups()
666+
e=e.exception
667+
self.assertEqual(str(e),'module cleanup failed (2 sub-exceptions)')
668+
self.assertEqual(str(e.exceptions[0]),'CleanUpExc2')
669+
self.assertEqual(str(e.exceptions[1]),'CleanUpExc1')
670+
671+
deftest_doModuleCleanup_with_exception_group_in_addModuleCleanup(self):
672+
defmodule_cleanup_bad():
673+
raiseExceptionGroup('CleanUpExc', [TypeError('CleanUpExc1'),
674+
ValueError('CleanUpExc2')])
675+
676+
classModule(object):
677+
unittest.addModuleCleanup(module_cleanup_bad)
678+
withself.assertRaises(ExceptionGroup)ase:
679+
unittest.case.doModuleCleanups()
680+
e=e.exception
681+
self.assertEqual(str(e),'module cleanup failed (1 sub-exception)')
682+
e=e.exceptions[0]
683+
self.assertEqual(str(e),'CleanUpExc (2 sub-exceptions)')
684+
self.assertEqual(str(e.exceptions[0]),'CleanUpExc1')
685+
self.assertEqual(str(e.exceptions[1]),'CleanUpExc2')
686+
654687
deftest_addModuleCleanup_arg_errors(self):
655688
cleanups= []
656689
defcleanup(*args,**kwargs):

‎Lib/unittest/case.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,9 @@ def doModuleCleanups():
149149
exceptExceptionasexc:
150150
exceptions.append(exc)
151151
ifexceptions:
152-
# Swallows all but first exception. If a multi-exception handler
153-
# gets written we should use that here instead.
154-
raiseexceptions[0]
152+
iflen(exceptions)==1andnotisinstance(exceptions[0],ExceptionGroup):
153+
raiseexceptions[0]
154+
raiseExceptionGroup('module cleanup failed',exceptions)
155155

156156

157157
defskip(reason):

‎Lib/unittest/suite.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,11 @@ def _handleModuleFixture(self, test, result):
223223
ifresult._moduleSetUpFailed:
224224
try:
225225
case.doModuleCleanups()
226+
exceptExceptionGroupaseg:
227+
foreineg.exceptions:
228+
self._createClassOrModuleLevelException(result,e,
229+
'setUpModule',
230+
currentModule)
226231
exceptExceptionase:
227232
self._createClassOrModuleLevelException(result,e,
228233
'setUpModule',
@@ -235,15 +240,15 @@ def _createClassOrModuleLevelException(self, result, exc, method_name,
235240
errorName=f'{method_name} ({parent})'
236241
self._addClassOrModuleLevelException(result,exc,errorName,info)
237242

238-
def_addClassOrModuleLevelException(self,result,exception,errorName,
243+
def_addClassOrModuleLevelException(self,result,exc,errorName,
239244
info=None):
240245
error=_ErrorHolder(errorName)
241246
addSkip=getattr(result,'addSkip',None)
242-
ifaddSkipisnotNoneandisinstance(exception,case.SkipTest):
243-
addSkip(error,str(exception))
247+
ifaddSkipisnotNoneandisinstance(exc,case.SkipTest):
248+
addSkip(error,str(exc))
244249
else:
245250
ifnotinfo:
246-
result.addError(error,sys.exc_info())
251+
result.addError(error,(type(exc),exc,exc.__traceback__))
247252
else:
248253
result.addError(error,info)
249254

@@ -273,6 +278,13 @@ def _handleModuleTearDown(self, result):
273278
previousModule)
274279
try:
275280
case.doModuleCleanups()
281+
exceptExceptionGroupaseg:
282+
ifisinstance(result,_DebugResult):
283+
raise
284+
foreineg.exceptions:
285+
self._createClassOrModuleLevelException(result,e,
286+
'tearDownModule',
287+
previousModule)
276288
exceptExceptionase:
277289
ifisinstance(result,_DebugResult):
278290
raise
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
:func:`unittest.doModuleCleanup` no longer swallows all but first exception
2+
raised in the cleanup code, but raises a:exc:`ExceptionGroup` if multiple
3+
errors occurred.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp