Deprecate and remove nose plugin · Issue #9886 · pytest-dev/pytest (original) (raw)
nose
has long been in maintenance only mode, and we support it via our nose.py
plugin.
The nose.py
plugin however is not trivial to maintain, and it dips its toes in a few places through the code:
def isnosetest(self, obj: object) -> bool: |
---|
"""Look for the __test__ attribute, which is applied by the |
@nose.tools.istest decorator. |
""" |
# We explicitly check for "is True" here to not mistakenly treat |
# classes with a custom __getattr__ returning something truthy (like a |
# function) as test classes. |
return safe_getattr(obj, "__test__", False) is True |
has_nose = self.config.pluginmanager.has_plugin("nose") |
---|
has_nose = self.config.pluginmanager.has_plugin("nose") |
---|
# This is actually only needed for nose, which reuses unittest.SkipTest for |
---|
# its own nose.SkipTest. For unittest TestCases, SkipTest is already |
# handled internally, and doesn't reach here. |
Also it can cause confusion such as in #9549.
Perhaps it is time to deprecate nose
, and eventually removing it? If there is a large test suite which still requires this, they can just pin pytest until the last version that still supports it.
It could become a third party plugin. but unless someone volunteers to do it, I don't think it should be pytest's core responsibility to maintain such a plugin.
How to deprecate it?
nose.py
actually just handles calling the nose-specific setup
and teardown
methods:
@hookimpl(trylast=True) |
---|
def pytest_runtest_setup(item: Item) -> None: |
if not isinstance(item, Function): |
return |
# Don't do nose style setup/teardown on direct unittest style classes. |
if isinstance(item, TestCaseFunction): |
return |
# Capture the narrowed type of item for the teardown closure, |
# see https://github.com/python/mypy/issues/2608 |
func = item |
call_optional(func.obj, "setup") |
func.addfinalizer(lambda: call_optional(func.obj, "teardown")) |
# NOTE: Module- and class-level fixtures are handled in python.py |
# with `pluginmanager.has_plugin("nose")` checks. |
# It would have been nicer to implement them outside of core, but |
# it's not straightforward. |
We could issue a deprecation warning when one of those functions are called, which AFAIK is basically what our nose support entails.