Home > Software engineering >  Set a class attribute in pytest fixture
Set a class attribute in pytest fixture

Time:04-29

I'm making a test class for pytest, I want to set a class attribute a that will be used for several test methods. To do so, I used a fixture set_a, which is launched automatically autouse=True, and invoked only once for the class (scope='class'), because setting a is costly. Here is my code:

import pytest
import time


class Test:

    @pytest.fixture(scope='class', autouse=True)
    def set_a(self):
        print('Setting a...')
        time.sleep(5)
        self.a = 1

    def test_1(self):
        print('TEST 1')
        assert self.a == 1

But the test fails with the following error:

========================================================================= FAILURES ==========================================================================
________________________________________________________________________ Test.test_1 ________________________________________________________________________

self = <tests.test_file.Test object at 0x116d953a0>

    def test_1(self):
        print('TEST 1')
>       assert self.a == 1
E       AttributeError: 'Test' object has no attribute 'a'

tests/test_file.py:15: AttributeError
------------------------------------------------------------------- Captured stdout setup -------------------------------------------------------------------
Setting a...
------------------------------------------------------------------- Captured stdout call --------------------------------------------------------------------
TEST 1

It looks like a wasn't set even if set_a was invoked, like if a new instance of the class was created when the test is executed.

It works well if I change the fixture scope to function, but I don't wan't to set a for each test.

Any idea what's the problem here ?

CodePudding user response:

You shouldn’t set the scope since you are already in the class.

class Test:
    @pytest.fixture(autouse=True)
    def set_a(self):
        print("Setting a...")
        time.sleep(5)
        self.a = 1

    def test_1(self):
        print("TEST 1")
        assert self.a == 1

This is how you should use the scope=class, meaning it will work for any class in your module:

@pytest.fixture(scope="class", autouse=True)
def a(request):
    print("Setting a...")
    time.sleep(5)
    request.cls.a = 1


class Test:
    def test_1(self):
        print("TEST 1")
        assert self.a == 1

CodePudding user response:

If the value never changes another option is to define it outside of the test method --

import pytest
import time


class Test:
    a = 1

    def test_1(self):
        print('TEST 1')
        assert self.a == 1
  • Related