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

Pytest async method fixture is run with different self than the test method #633

Open
2 tasks done
Guerilla94 opened this issue Nov 16, 2023 · 8 comments
Open
2 tasks done
Labels
bug Something isn't working

Comments

@Guerilla94
Copy link

Things to check first

  • I have searched the existing issues and didn't find my bug already reported there

  • I have checked that my bug is still present in the latest release

AnyIO version

4.0.0

Python version

3.11.4

What happened?

I'm trying to use an fixture class method to initialize some data for tests and store it in attributes. With synchronous fixture everything works as expected, the filled attributes are available in the test methods. But attributes filled in async function are not available in test methods. This happens because different objects are passed as "self" for the fixture and the test method.

I found similar issue for pytest-asyncio which was fixed

How can we reproduce the bug?

import pytest


class TestSomething:
    @pytest.fixture()
    async def do_setup(self):
        self.some_attr = 'value'

        print()
        print('in fixture')
        print(self)
        print(self.__dict__)

    async def test_something(self, do_setup):
        print()
        print('in test')
        print(self)          # different object
        print(self.__dict__) # some_attr missing

Output:

in fixture
<tests.test_anyio.TestSomething object at 0x107b0ca50>
{'some_attr': 'value'}

in test
<tests.test_anyio.TestSomething object at 0x107f06590>
{}
@Guerilla94 Guerilla94 added the bug Something isn't working label Nov 16, 2023
@agronholm
Copy link
Owner

Linking the pytest-asyncio fix PR here: pytest-dev/pytest-asyncio#439

@agronholm
Copy link
Owner

Meanwhile I suggest that you don't assign anything to the instance. That's not the correct way to use fixtures.

@Guerilla94
Copy link
Author

Guerilla94 commented Nov 16, 2023

Assigning something to an instance looks strange when using a fixture directly. We usually use a fixture with autouse=True to initialize data for all tests in a class:

class TestSomething:
    @pytest.fixture(autouse=True)
    def _setup(self):
        self.some_attr = 'value'

In this case, assigning to an instance seems more justifiable. Or in this case assigning to the instance is also not the correct way?

I didn't include autouse in the reproduction example because it doesn't affect the problem

@agronholm
Copy link
Owner

Why not return the value from the fixture?

@Guerilla94
Copy link
Author

To do this, you will have to specify in each test of class the use of the fixture directly instead of autouse. It looks like boilerplate when each test in the class directly uses same setup fixture:

class TestSomething:
    @pytest.fixture()
    async def setup_data(self):
        return {}

    async def test_something(self, setup_data):
        pass

    async def test_something_else(self, setup_data):
        pass

    async def test_something_else2(self, setup_data):
        pass

Additionally, not all tests require data from the setup, but the setup process is still necessary. In this case it is easy to forget to specify setup fixture for test

@agronholm
Copy link
Owner

Is there something preventing you from using autouse=True on that fixture then?

@Guerilla94
Copy link
Author

Thank you, now I understand your point. I haven't thought about using a fixture with autouse=True directly if result is needed. I'll need to rethink the use of fixtures. Looks like it would be better not to use assigning to instance in fixtures.

Therefore, I think that this behavior can be left as is. It seems that the issue can be closed

@agronholm
Copy link
Owner

Therefore, I think that this behavior can be left as is. It seems that the issue can be closed

I disagree. This plugin should not make pytest deviate from how it normally works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants