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:
Additional Context:
Thank you in advance for your help!
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.