Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

autouse fixtures break scope rules #668

Closed
pytestbot opened this issue Jan 26, 2015 · 2 comments
Closed

autouse fixtures break scope rules #668

pytestbot opened this issue Jan 26, 2015 · 2 comments
Labels
type: bug problem that needs to be addressed

Comments

@pytestbot
Copy link
Contributor

Originally reported by: BitBucket: tgoodlet, GitHub: tgoodlet


I believe this issue is very similar to #660

The problem is easily reproduced.
Say you have the following very simple test mod test_fixture_scopes.py

import pytest


@pytest.fixture
def func_level(request):
    return 'blah'


@pytest.fixture(scope='session')
def sess_level(func_level):
    return func_level


def test_fscopes(sess_level):
    print sess_level

As expected this fixture chain breaks scope rules:

$ py.test --tb=short ./test_fixture_scopes
============================================================================================================= test session starts ==========================
platform linux2 -- Python 2.7.9 -- py-1.4.26 -- pytest-2.6.4 -- /usr/bin/python2
plugins: interactive, ordering, ipdb
collected 1 items 

test_fixture_scopes.py::test_fscopes ERROR

=================================================================================================================== ERRORS ==========================
_______________________________________________________________________________________________________ ERROR at setup of test_fscopes ________________________________________________________________________________________________________
/usr/lib/python2.7/site-packages/_pytest/runner.py:139: in __init__
    self.result = func()
/usr/lib/python2.7/site-packages/_pytest/runner.py:127: in <lambda>
    return CallInfo(lambda: ihook(item=item, **kwds), when=when)
/usr/lib/python2.7/site-packages/_pytest/main.py:167: in call_matching_hooks
    return hookmethod.pcall(plugins, **kwargs)
/usr/lib/python2.7/site-packages/_pytest/core.py:417: in pcall
    return self._docall(methods, kwargs)
/usr/lib/python2.7/site-packages/_pytest/core.py:424: in _docall
    res = mc.execute()
/usr/lib/python2.7/site-packages/_pytest/core.py:315: in execute
    res = method(**kwargs)
/usr/lib/python2.7/site-packages/_pytest/runner.py:86: in pytest_runtest_setup
    item.session._setupstate.prepare(item)
/usr/lib/python2.7/site-packages/_pytest/runner.py:393: in prepare
    col.setup()
/usr/lib/python2.7/site-packages/_pytest/python.py:1141: in setup
    fillfixtures(self)
/usr/lib/python2.7/site-packages/_pytest/python.py:667: in fillfixtures
    request._fillfixtures()
/usr/lib/python2.7/site-packages/_pytest/python.py:1289: in _fillfixtures
    item.funcargs[argname] = self.getfuncargvalue(argname)
/usr/lib/python2.7/site-packages/_pytest/python.py:1337: in getfuncargvalue
    return self._get_active_fixturedef(argname).cached_result[0]
/usr/lib/python2.7/site-packages/_pytest/python.py:1351: in _get_active_fixturedef
    result = self._getfuncargvalue(fixturedef)
/usr/lib/python2.7/site-packages/_pytest/python.py:1403: in _getfuncargvalue
    val = fixturedef.execute(request=subrequest)
/usr/lib/python2.7/site-packages/_pytest/python.py:1825: in execute
    fixturedef = request._get_active_fixturedef(argname)
/usr/lib/python2.7/site-packages/_pytest/python.py:1351: in _get_active_fixturedef
    result = self._getfuncargvalue(fixturedef)
E   ScopeMismatchError: You tried to access the 'function' scoped fixture 'func_level' with a 'session' scoped request object, involved factories
E   test_fixture_scopes.py:3:  def sess_level(func_level)
E   test_fixture_scopes.py:8:  def func_level(request)
=========================================================================================================== 1 error in 0.04 seconds ==========================

But now add a sibling autouse fixture which consumes sess_level to the same file:

@pytest.fixture(autouse=True)
    def always(func_level):
        print func_level

Run again and the scope mismatch error dissappears?

$ py.test --tb=short ./test_fixture_scopes
============================================================================================================= test session starts =================================================================
platform linux2 -- Python 2.7.9 -- py-1.4.26 -- pytest-2.6.4 -- /usr/bin/python2
plugins: interactive, ordering, ipdb
collected 1 items 

test_fixture_scopes.py::test_fscopes blah
blah
PASSED

========================================================================================================== 1 passed in 0.01 seconds ========================

This caused some very unexpected results for me since the scoped sess_level will be retriggered for every consuming test once the autouse sibling is added.
Since there was no error and I am dealing with a large fixture set, I was unaware that I was breaking scope rules and instead saw odd fixture execution orders.


@pytestbot pytestbot added the type: bug problem that needs to be addressed label Jun 15, 2015
@ghostsquad
Copy link

This issue seems like it breaks the Dependency Inversion principle.

https://en.wikipedia.org/wiki/Dependency_inversion_principle

session level fixture shouldn't care about the function level fixture. The opposite seems ok though.

This works:

@pytest.fixture(scope='session')
def sess_level(request):
    return 'session_lvl'

@pytest.fixture(scope='function')
def func_level(sess_level):
    return sess_level + ' -> func_lvl'

def test_fscopes(func_level):
    print func_level

@nicoddemus
Copy link
Member

Hi @tgoodlet,

Trying your example with 2.7.2 works as expected now:

_______________________ ERROR at setup of test_fscopes ________________________
ScopeMismatch: You tried to access the 'function' scoped fixture 'func_level' with a 'session' scoped request object, involved factories
test_sess.py:12:  def sess_level(func_level)

So I'm closing this. Thanks! 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug problem that needs to be addressed
Projects
None yet
Development

No branches or pull requests

3 participants