Search code examples
pythonpycharmpytestpython-decoratorspytest-fixtures

Pytest Fixtures Not Found When Running Tests from PyCharm IDE


I am having trouble with pytest fixtures in my project. I have a root conftest.py file with some general-use fixtures and isolated conftest.py files for specific tests. The folder structure is as follows:

product-testing/
├── conftest.py  # Root conftest.py
├── tests/
│   └── grpc_tests/
│       └── collections/
│           └── test_collections.py
└── fixtures/
    └── collections/
        └── conftest.py  # Used by test_collections.py specifically

When I try to run the tests from the IDE (PyCharm) using the "run button" near the test function, pytest can't initialize fixtures from the root conftest.py. The test code is something like this:

import datetime
import allure
from faker import Faker
from fixtures.collections.conftest import collection

fake = Faker()

@allure.title("Get list of collections")
def test_get_collections_list(collection, postgres):
    with allure.step("Send request to get the collection"):
        response = collection.collection_list(
            limit=1,
            offset=0,
            # ...And the rest of the code
        )

here is a contest from fixtures/collection/

import datetime
import pytest

from faker import Faker
from path.to.file import pim_collections_pb2

fake = Faker()


@pytest.fixture(scope="session")
def collection(grpc_pages):
    def create_collection(collection_id=None, store_name=None, items_ids=None, **kwargs):
        default_params = {
            "id": collection_id,
            "store_name": store_name,
            "item_ids": items_ids,
            "is_active": True,
            "description_eng": fake.text(),
            # rest of the code

and this is the root conftest.py file

import pytest
from faker import Faker

from pages.manager import DBManager, GrpcPages, RestPages

fake = Faker()


@pytest.fixture(scope="session")
def grpc_pages():
    return GrpcPages()


@pytest.fixture(scope="session")
def rest_pages():
    return RestPages()


@pytest.fixture(scope="session")
def postgres():
    return DBManager()

#some other code

The error message I get is:

test setup failed
file .../tests/grpc_tests/collections/test_collections.py, line 9
    @allure.title("Create a multi-collection")
    def test_create_multicollection(collection, postgres):

file .../fixtures/collections/conftest.py, line 10
    @pytest.fixture(scope="session")
    def collection(grpc_pages):
E       fixture 'grpc_pages' not found
>       available fixtures: *session*faker, cache, capfd, capfdbinary, caplog, capsys, capsysbinary, collection, doctest_namespace, factoryboy_request, faker, monkeypatch, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory
>       use 'pytest --fixtures [testpath]' for help on them.

However, when I run the tests through a terminal with pytest ., there is no error. It seems like pytest can see the root conftest.py in one case but not in another.

I have tried to Explicitly importing the missing fixtures directly from the root conftest.py to resolve the issue. This works for single test runs but causes errors when running all tests using CLI commands like pytest ., with the following error:

```
ImportError while importing test module '/path/to/test_collections.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
.../importlib/init.py:127: in import_module
    return bootstrap.gcd_import(name[level:], package, level)
tests/.../test_collections.py:6: in <module>
    from conftest import grpc_pages
E   ImportError: cannot import name 'grpc_pages' from 'conftest' (/path/to/fixtures/users/conftest.py)
```

It feels like pytest is trying to find grpc_pages in the isolated conftest.py instead of the root file.

Also, running isolated tests through a command like

  • pytest -k "test_create_multicollection" ./tests/grpc_tests/collections/
  • pytest path/to/test_collections.py::test_create_multicollection

works when the import is not explicit. However, I need to make the run button in the IDE work for less experienced, non-technical team members.

So my questions are:

  1. Has anyone encountered this issue where PyCharm can't find fixtures from the root conftest.py when running individual tests, but pytest can when run from the command line?
  2. How can I fix this so that both PyCharm's run button and command-line pytest work consistently?

Additional Context:

  • Pytest version: pytest 7.4.4
  • PyCharm version: 2023.2.1
  • Python version: 3.9.6

Thank you in advance for your help!


Solution

  • After hours of debugging and calls I found the solution, IDK maybe one day it will help someone. First of all, putting contest files in a separate directory from pytest is not a good idea, pytest can't see the files, so the files should be put in the same directory or at least on the path to the test file. So I have moved the files from the fixtures folder to the tests folder.

    product-testing/
    ├── conftest.py  # Root conftest.py
    ├── tests/
    │   └── grpc_tests/
    │       └── collections/
    │           └── test_collections.py
    │           └── conftest.py  # Used by test_collections.py specifically
    
    

    Also, I got rid of explicitly importing all conftest files and functions from the file as pytest should handle it by itself. The code is like this.

    import datetime
    import allure
    from faker import Faker
    #from fixtures.collections.conftest import collection -> get rid of this file
    
    fake = Faker()
    
    @allure.title("Get list of collections")
    def test_get_collections_list(collection, postgres):
        with allure.step("Send request to get the collection"):
            response = collection.collection_list(
                limit=1,
                offset=0,
                # ...And the rest of the code
            )
    
    

    And last but not least, I have changed the root testing directory to the root folder of the project by right-clicking on the project folder and choosing Mark directory As > Test Source Root

    These changes were made based on the official documentation of pytest and they solved my issues.