pytest-dev / pytest

The pytest framework makes it easy to write small tests, yet scales to support complex functional testing
https://pytest.org
MIT License
11.9k stars 2.65k forks source link

Support per-request scope for fixtures #456

Open pytestbot opened 10 years ago

pytestbot commented 10 years ago

Originally reported by: BitBucket: brettatoms, GitHub: brettatoms


I'm not sure how to really describe this but here's a code sample that demonstrates the issue. Basically if I create a test that takes two fixtures as parameters and one of those fixtures depends on the other fixture then the fixture only gets called once and the test method has the same instance for both fixtures.

import sys
import pytest

class User:
    def __init__(self, username, is_admin=False):
        self.username = username
        self.is_admin = is_admin

@pytest.fixture
def user():
    return User('me')

@pytest.fixture
def admin_user(user):
    user.username = 'admin'
    user.is_admin = True
    return user

def test_me(user, admin_user):
    print('repr(user): ', repr(user))
    print('repr(admin_user): ', repr(admin_user))
pytestbot commented 10 years ago

Original comment by Floris Bruynooghe (BitBucket: flub, GitHub: flub):


I think this is actually intended to work as you describe.

The quick work around it just to build admin_user without relying on user I guess.

And I reckon the real issue here is probably a feature request: be able to have a scope which is called each time instead of once per test run. This reminds me of the scope discussions surrounding tmpdir where some people want a per-fixture directory and some people a per-test directory (and also has the problem of scope-mismatches).

RonnyPfannschmidt commented 8 years ago

closing as unclear

The-Compiler commented 8 years ago

Not sure what's unclear about it - reopening because I might want to work at it at the sprint :wink:

earonesty commented 5 years ago

This is a feature. The nature of "fixtures" is that they are invariant by name.

There is a slightly different concept of have a fixture-generator syntax, so that fixtures autovivify if referred to as a keyword. If keyword arguments were able to be used in this way, it would be possible to indicate that a fixture was intended to be a "new instance".

@pytest.fixture
def admin_user(_unique_user=user):
    _unique_user.username = 'admin'
    _unique_useris_admin = True
    return _unique_user

def test_user_instance_equal(user_x=user, user_y=user):
    assert not user_x is user_y
    assert user_x == user_y

(I personally like the convention that assigning to names beginning with '_' means private/local)

See: https://github.com/pytest-dev/pytest/issues/2703