Skip to content

Refactor: move no_rerun from test_import and datetimetester to test.support #119659

Description

@sobolevn

Feature or enhancement

It is defined here:

def no_rerun(reason):
"""Skip rerunning for a particular test.
WARNING: Use this decorator with care; skipping rerunning makes it
impossible to find reference leaks. Provide a clear reason for skipping the
test using the 'reason' parameter.
"""
def deco(func):
_has_run = False
def wrapper(self):
nonlocal _has_run
if _has_run:
self.skipTest(reason)
func(self)
_has_run = True
return wrapper
return deco

and here:

# This is copied from test_import/__init__.py.
# XXX Move it to support/__init__.py.
def no_rerun(reason):
"""Skip rerunning for a particular test.
WARNING: Use this decorator with care; skipping rerunning makes it
impossible to find reference leaks. Provide a clear reason for skipping the
test using the 'reason' parameter.
"""
def deco(func):
_has_run = False
def wrapper(self):
nonlocal _has_run
if _has_run:
self.skipTest(reason)
func(self)
_has_run = True
return wrapper
return deco

Introduced in #119373

Linked PRs

Activity

  1. added
    type-featureA feature request or enhancement
    testsTests in the Lib/test dir
    on May 28, 2024
  2. self-assigned this
    on May 28, 2024
  3. added 2 commits that reference this issue on May 28, 2024
  4. sobolevn commented on May 28, 2024

    @sobolevn
    MemberAuthor

    aaaand I found a bug:

    def no_rerun(reason):
    """Skip rerunning for a particular test.
    WARNING: Use this decorator with care; skipping rerunning makes it
    impossible to find reference leaks. Provide a clear reason for skipping the
    test using the 'reason' parameter.
    """
    def deco(func):
    _has_run = False
    def wrapper(self):
    nonlocal _has_run
    if _has_run:
    self.skipTest(reason)
    func(self)
    _has_run = True
    return wrapper
    return deco

    this code does not work well when applied to classes.

    proof (with @no_rerun decorator):

    @unittest.skipIf(_testcapi is None, 'need _testcapi module')
    @no_rerun("the encapsulated datetime C API does not support reloading")
    class CapiTest(unittest.TestCase):
    def setUp(self):
    # Since the C API is not present in the _Pure tests, skip all tests
    if self.__class__.__name__.endswith('Pure'):
    self.skipTest('Not relevant in pure Python')

    » ./python.exe -m test test_datetime -m test_utc_capi -v
    == CPython 3.14.0a0 (heads/main:669175bf8ed, May 28 2024, 13:18:18) [Clang 15.0.0 (clang-1500.3.9.4)]
    == macOS-14.4.1-arm64-arm-64bit-Mach-O little-endian
    == Python build: debug
    == cwd: /Users/sobolev/Desktop/cpython2/build/test_python_worker_98352æ
    == CPU count: 12
    == encodings: locale=UTF-8 FS=utf-8
    == resources: all test resources are disabled, use -u option to unskip tests
    
    Using random seed: 1630075014
    0:00:00 load avg: 2.16 Run 1 test sequentially
    0:00:00 load avg: 2.16 [1/1] test_datetime
    
    ----------------------------------------------------------------------
    Ran 0 tests in 0.000s
    
    NO TESTS RAN
    test_datetime ran no tests
    
    == Tests result: NO TESTS RAN ==
    
    1 test run no tests:
        test_datetime
    
    Total duration: 124 ms
    Total tests: run=0 (filtered)
    Total test files: run=1/1 (filtered) run_no_tests=1
    Result: NO TESTS RAN
    

    Without:

    » ./python.exe -m test test_datetime -m test_utc_capi -v
    == CPython 3.14.0a0 (heads/main:669175bf8ed, May 28 2024, 13:18:18) [Clang 15.0.0 (clang-1500.3.9.4)]
    == macOS-14.4.1-arm64-arm-64bit-Mach-O little-endian
    == Python build: debug
    == cwd: /Users/sobolev/Desktop/cpython2/build/test_python_worker_98457æ
    == CPU count: 12
    == encodings: locale=UTF-8 FS=utf-8
    == resources: all test resources are disabled, use -u option to unskip tests
    
    Using random seed: 1077352783
    0:00:00 load avg: 1.75 Run 1 test sequentially
    0:00:00 load avg: 1.75 [1/1] test_datetime
    test_utc_capi (test.datetimetester.CapiTest_Pure.test_utc_capi) ... skipped 'Not relevant in pure Python'
    test_utc_capi (test.datetimetester.CapiTest_Fast.test_utc_capi) ... ok
    
    ----------------------------------------------------------------------
    Ran 2 tests in 0.000s
    
    OK (skipped=1)
    
    == Tests result: SUCCESS ==
    
    1 test OK.
    
    Total duration: 130 ms
    Total tests: run=2 (filtered) skipped=1
    Total test files: run=1/1 (filtered)
    Result: SUCCESS
    

    Turns out it is not just "moving", I also have to fix it for both types and methods.

  5. sobolevn commented on May 28, 2024

    @sobolevn
    MemberAuthor

    Aaaand I found another one: test_datetime forgets about existing setUpClass and tearDownClass:

    for cls in test_classes:
    cls.__name__ += suffix
    cls.__qualname__ += suffix
    @classmethod
    def setUpClass(cls_, module=module):
    cls_._save_sys_modules = sys.modules.copy()
    sys.modules[TESTS] = module
    sys.modules['datetime'] = module.datetime_module
    if hasattr(module, '_pydatetime'):
    sys.modules['_pydatetime'] = module._pydatetime
    sys.modules['_strptime'] = module._strptime
    @classmethod
    def tearDownClass(cls_):
    sys.modules.clear()
    sys.modules.update(cls_._save_sys_modules)
    cls.setUpClass = setUpClass
    cls.tearDownClass = tearDownClass
    tests.addTests(loader.loadTestsFromTestCase(cls))

  6. sobolevn commented on May 28, 2024

    @sobolevn
    MemberAuthor

    And the whole nonlocal _has_run idea simply does not work 🙈
    Because on each run the test class is different.

    Wow, what a ride! 😄

  7. added a commit that references this issue on May 28, 2024
  8. added a commit that references this issue on Jun 7, 2024
  9. added a commit that references this issue on Jul 11, 2024
  10. added 2 commits that reference this issue on Jul 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

testsTests in the Lib/test dirtype-featureA feature request or enhancement

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions