1111import locale
1212import os .path
1313import platform
14+ import random
1415import re
1516import subprocess
1617import sys
@@ -504,7 +505,7 @@ def list_regex(line_format, tests):
504505 if rerun is not None :
505506 regex = list_regex ('%s re-run test%s' , [rerun .name ])
506507 self .check_line (output , regex )
507- regex = LOG_PREFIX + fr "Re-running 1 failed tests in verbose mode"
508+ regex = LOG_PREFIX + r "Re-running 1 failed tests in verbose mode"
508509 self .check_line (output , regex )
509510 regex = fr"Re-running { rerun .name } in verbose mode"
510511 if rerun .match :
@@ -1018,13 +1019,13 @@ def test_run(self):
10181019 stats = TestStats (4 , 1 ),
10191020 forever = True )
10201021
1021- def check_leak (self , code , what , * , multiprocessing = False ):
1022+ def check_leak (self , code , what , * , run_workers = False ):
10221023 test = self .create_test ('huntrleaks' , code = code )
10231024
10241025 filename = 'reflog.txt'
10251026 self .addCleanup (os_helper .unlink , filename )
10261027 cmd = ['--huntrleaks' , '6:3:' ]
1027- if multiprocessing :
1028+ if run_workers :
10281029 cmd .append ('-j1' )
10291030 cmd .append (test )
10301031 output = self .run_tests (* cmd ,
@@ -1043,7 +1044,7 @@ def check_leak(self, code, what, *, multiprocessing=False):
10431044 self .assertIn (line2 , reflog )
10441045
10451046 @unittest .skipUnless (support .Py_DEBUG , 'need a debug build' )
1046- def check_huntrleaks (self , * , multiprocessing : bool ):
1047+ def check_huntrleaks (self , * , run_workers : bool ):
10471048 # test --huntrleaks
10481049 code = textwrap .dedent ("""
10491050 import unittest
@@ -1054,13 +1055,13 @@ class RefLeakTest(unittest.TestCase):
10541055 def test_leak(self):
10551056 GLOBAL_LIST.append(object())
10561057 """ )
1057- self .check_leak (code , 'references' , multiprocessing = multiprocessing )
1058+ self .check_leak (code , 'references' , run_workers = run_workers )
10581059
10591060 def test_huntrleaks (self ):
1060- self .check_huntrleaks (multiprocessing = False )
1061+ self .check_huntrleaks (run_workers = False )
10611062
10621063 def test_huntrleaks_mp (self ):
1063- self .check_huntrleaks (multiprocessing = True )
1064+ self .check_huntrleaks (run_workers = True )
10641065
10651066 @unittest .skipUnless (support .Py_DEBUG , 'need a debug build' )
10661067 def test_huntrleaks_fd_leak (self ):
@@ -1138,8 +1139,6 @@ def test_method3(self):
11381139 def test_method4(self):
11391140 pass
11401141 """ )
1141- all_methods = ['test_method1' , 'test_method2' ,
1142- 'test_method3' , 'test_method4' ]
11431142 testname = self .create_test (code = code )
11441143
11451144 # only run a subset
@@ -1761,7 +1760,7 @@ def test_mp_decode_error(self):
17611760 if encoding is None :
17621761 encoding = sys .__stdout__ .encoding
17631762 if encoding is None :
1764- self .skipTest (f "cannot get regrtest worker encoding" )
1763+ self .skipTest ("cannot get regrtest worker encoding" )
17651764
17661765 nonascii = b"byte:\xa0 \xa9 \xff \n "
17671766 try :
@@ -1788,7 +1787,7 @@ def test_mp_decode_error(self):
17881787 stats = 0 )
17891788
17901789 def test_doctest (self ):
1791- code = textwrap .dedent (fr '''
1790+ code = textwrap .dedent (r '''
17921791 import doctest
17931792 import sys
17941793 from test import support
@@ -1826,6 +1825,46 @@ def load_tests(loader, tests, pattern):
18261825 randomize = True ,
18271826 stats = TestStats (1 , 1 , 0 ))
18281827
1828+ def _check_random_seed (self , run_workers : bool ):
1829+ # gh-109276: When -r/--randomize is used, random.seed() is called
1830+ # with the same random seed before running each test file.
1831+ code = textwrap .dedent (r'''
1832+ import random
1833+ import unittest
1834+
1835+ class RandomSeedTest(unittest.TestCase):
1836+ def test_randint(self):
1837+ numbers = [random.randint(0, 1000) for _ in range(10)]
1838+ print(f"Random numbers: {numbers}")
1839+ ''' )
1840+ tests = [self .create_test (name = f'test_random{ i } ' , code = code )
1841+ for i in range (1 , 3 + 1 )]
1842+
1843+ random_seed = 856_656_202
1844+ cmd = ["--randomize" , f"--randseed={ random_seed } " ]
1845+ if run_workers :
1846+ # run as many worker processes than the number of tests
1847+ cmd .append (f'-j{ len (tests )} ' )
1848+ cmd .extend (tests )
1849+ output = self .run_tests (* cmd )
1850+
1851+ random .seed (random_seed )
1852+ # make the assumption that nothing consume entry between libregrest
1853+ # setup_tests() calls random.seed() and RandomSeedTest calling
1854+ # random.randint().
1855+ numbers = [random .randint (0 , 1000 ) for _ in range (10 )]
1856+ expected = f"Random numbers: { numbers } "
1857+
1858+ regex = r'^Random numbers: .*$'
1859+ matches = re .findall (regex , output , flags = re .MULTILINE )
1860+ self .assertEqual (matches , [expected ] * len (tests ))
1861+
1862+ def test_random_seed (self ):
1863+ self ._check_random_seed (run_workers = False )
1864+
1865+ def test_random_seed_workers (self ):
1866+ self ._check_random_seed (run_workers = True )
1867+
18291868
18301869class TestUtils (unittest .TestCase ):
18311870 def test_format_duration (self ):
0 commit comments