Skip to content

Commit bd57307

Browse files
authored
Merge pull request #5768 from robholt/fixture-class-instance
Fix self reference in function scoped fixtures
2 parents 667c646 + 955dc6d commit bd57307

File tree

4 files changed

+41
-0
lines changed

4 files changed

+41
-0
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ Raphael Castaneda
211211
Raphael Pierzina
212212
Raquel Alegre
213213
Ravi Chandra
214+
Robert Holt
214215
Roberto Polli
215216
Roland Puntaier
216217
Romain Dorgueil

changelog/2270.bugfix.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fixed ``self`` reference in function-scoped fixtures defined plugin classes: previously ``self``
2+
would be a reference to a *test* class, not the *plugin* class.

src/_pytest/fixtures.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -900,6 +900,12 @@ def resolve_fixture_function(fixturedef, request):
900900
# request.instance so that code working with "fixturedef" behaves
901901
# as expected.
902902
if request.instance is not None:
903+
# handle the case where fixture is defined not in a test class, but some other class
904+
# (for example a plugin class with a fixture), see #2270
905+
if hasattr(fixturefunc, "__self__") and not isinstance(
906+
request.instance, fixturefunc.__self__.__class__
907+
):
908+
return fixturefunc
903909
fixturefunc = getimfunc(fixturedef.func)
904910
if fixturefunc != fixturedef.func:
905911
fixturefunc = fixturefunc.__get__(request.instance)

testing/python/fixtures.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3946,6 +3946,38 @@ def test_2(fix):
39463946
reprec = testdir.inline_run()
39473947
reprec.assertoutcome(passed=2)
39483948

3949+
def test_class_fixture_self_instance(self, testdir):
3950+
"""Check that plugin classes which implement fixtures receive the plugin instance
3951+
as self (see #2270).
3952+
"""
3953+
testdir.makeconftest(
3954+
"""
3955+
import pytest
3956+
3957+
def pytest_configure(config):
3958+
config.pluginmanager.register(MyPlugin())
3959+
3960+
class MyPlugin():
3961+
def __init__(self):
3962+
self.arg = 1
3963+
3964+
@pytest.fixture(scope='function')
3965+
def myfix(self):
3966+
assert isinstance(self, MyPlugin)
3967+
return self.arg
3968+
"""
3969+
)
3970+
3971+
testdir.makepyfile(
3972+
"""
3973+
class TestClass(object):
3974+
def test_1(self, myfix):
3975+
assert myfix == 1
3976+
"""
3977+
)
3978+
reprec = testdir.inline_run()
3979+
reprec.assertoutcome(passed=1)
3980+
39493981

39503982
def test_call_fixture_function_error():
39513983
"""Check if an error is raised if a fixture function is called directly (#4545)"""

0 commit comments

Comments
 (0)