Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions src/_pytest/python.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,16 @@ def cls(self):
node = self.getparent(Class)
return node.obj if node is not None else None

@property
def instance(self):
"""Python instance object the function is bound to.

Returns None if not a test method, e.g. for a standalone test function,
a staticmethod, a class or a module.
"""
node = self.getparent(Function)
return getattr(node.obj, "__self__", None) if node is not None else None

@property
def obj(self):
"""Underlying Python object."""
Expand Down Expand Up @@ -1689,15 +1699,6 @@ def function(self):
"""Underlying python 'function' object."""
return getimfunc(self.obj)

@property
def instance(self):
"""Python instance object the function is bound to.

Returns None if not a test method, e.g. for a standalone test function
or a staticmethod.
"""
return getattr(self.obj, "__self__", None)

def _getobj(self):
assert self.parent is not None
if isinstance(self.parent, Class):
Expand Down
25 changes: 16 additions & 9 deletions testing/test_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def test_fail(): assert 0

assert pytester.collect_by_name(modcol, "doesnotexist") is None

def test_getparent(self, pytester: Pytester) -> None:
def test_getparent_and_accessors(self, pytester: Pytester) -> None:
modcol = pytester.getmodulecol(
"""
class TestClass:
Expand All @@ -77,14 +77,21 @@ def test_foo(self):
fn = pytester.collect_by_name(cls, "test_foo")
assert isinstance(fn, pytest.Function)

module_parent = fn.getparent(pytest.Module)
assert module_parent is modcol

function_parent = fn.getparent(pytest.Function)
assert function_parent is fn

class_parent = fn.getparent(pytest.Class)
assert class_parent is cls
assert fn.getparent(pytest.Module) is modcol
assert modcol.module is not None
assert modcol.cls is None
assert modcol.instance is None

assert fn.getparent(pytest.Class) is cls
assert cls.module is not None
assert cls.cls is not None
assert cls.instance is None

assert fn.getparent(pytest.Function) is fn
assert fn.module is not None
assert fn.cls is not None
assert fn.instance is not None
assert fn.function is not None

def test_getcustomfile_roundtrip(self, pytester: Pytester) -> None:
hello = pytester.makefile(".xxx", hello="world")
Expand Down