Skip to content

unittest.skip and other decorators should complain if the argument isn't callable #116428

Open
@geofft

Description

@geofft

Bug report

Bug description:

The practical motivation here is that the third-party decorator parameterized.parameterized.expand from the parameterized project works by generating more test methods in the containing class, one for each expansion, and then returning None as the result of the decorator. So if you do something like

import unittest
import parameterized

class TestStuff(unittest.TestCase):
    @unittest.skip("these tests modify prod")
    @parameterized.parameterized.expand([("a", 1), ("b", 2)])
    def test_stuff(self, x, y):
        ...

then the tests actually get run. The correct way to implement this is the other way around - use @expand(...) @skip(...), and then parameterized will copy the skip wrapper, giving the behavior the programmer expects.

The underlying reason is that unittest.skip's decorator never actually calls the function its decorating and therefore doesn't care what it is:

>>> import unittest
>>> unittest.skip("these tests modify prod")(None)
<function skip.<locals>.decorator.<locals>.skip_wrapper at 0x10082c1f0>
>>> _()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/unittest/case.py", line 119, in skip_wrapper
    raise SkipTest(reason)
unittest.case.SkipTest: these tests modify prod

If unittest.skip(reason)(function) were to instead raise an error if callable(function) is false, instead of returning a wrapper, then the test case above would raise at import time, before any of the tests were run, indicating to the test author that they have implemented something incorrectly.

This should also apply to skipIf and skipUnless, and I think also to expectedFailure and removeHandler, the other decorators in unittest.

CPython versions tested on:

3.9, 3.10, 3.11, 3.12

Operating systems tested on:

Linux, macOS

Metadata

Metadata

Assignees

No one assigned

    Labels

    stdlibPython modules in the Lib dirtype-featureA feature request or enhancement

    Projects

    Status

    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions