Sourya Dey
Sourya Dey

Reputation: 1634

Some Pytest fixture attributes don't get reset after each test

I have a Python class like this:

class Foo:
    def __init__(self, r=range(10)):
        self.r = r
    def bar(self):
        # code
    def hop(self):
        # code

and I want to test it like this:

@pytest.fixture()
def foo():
    return Foo()

def test_bar(foo):
    # run tests
    foo.r = range(20)
    # run more tests

def test_hop(foo):
    # run tests

I want the value of foo.r in test_hop() to be range(10), but instead it's range(20). Why is the value not getting reset?

I tried re-defining the fixture decorator as @pytest.fixture(scope='function') (this is the default value, but I wanted to make sure that the fixture was getting 'torn down' at the end of each test). It made no difference to the result.

Upvotes: 0

Views: 904

Answers (1)

Sourya Dey
Sourya Dey

Reputation: 1634

This is happening because ranges in Python are mutable. Thus, any changes made inside a test function will persist in subsequent test functions. Had the argument r to __init__() been something immutable, the fixture would have reset between tests as expected.

One way to get around this is to define r as a tuple containing the limits of the range (tuples are immutable). Then, create the actual range variable inside __init__(), i.e.:

class Foo:
    def __init__(self, r=tuple(0,10)):
        self.r = range(r[0],r[1])
    def bar(self):
        # code
    def hop(self):
        # code

Now, the value of foo.r in test_hop() will be range(10).

Upvotes: 1

Related Questions