In pytest, conftest.py is used for several key purposes:
Fixtures: Define reusable fixtures for your tests. These fixtures can be accessed across your entire test suite, unless otherwise scoped.
Plugins: Load external plugins or modules by specifying pytest_plugins = “someapp.someplugin”. This allows Pytest to recognize and use these plugins during testing.
Hooks: Implement hooks like setup and teardown methods to customize test behavior. For example, pytest_runtest_setup(item) runs before each test.
Test Root Path: By placing conftest.py in the root directory, you can avoid setting PYTHONPATH manually, as Pytest will include all submodules automatically.
Coming to your second question: Can you have multiple conftest.py files?
Yes, you can. Having multiple conftest.py files allows you to:
Scope Fixtures: Define fixtures specific to different directories or test modules.
Override Hooks: Implement different hooks for different parts of your test suite.
Directory-Specific Fixtures:
root/mod/conftest.py:
@pytest.fixture
def fixture():
return "some stuff"
root/mod2/conftest.py:
@pytest.fixture
def fixture():
return "some other stuff"
root/mod2/test.py:
def test(fixture):
print(fixture) # Outputs: "some other stuff"
Override Hooks:
root/conftest.py:
def pytest_runtest_setup(item):
print("I am root")
root/mod/conftest.py:
def pytest_runtest_setup(item):
print("I am mod")
Running tests in root/mod will print “I am mod”, while tests in the root directory will print “I am root”.
Helper Functions: You can put simple helper functions in conftest.py, but for reusable helpers across tests, consider placing them in a separate module and importing them where needed.
For example:
root/tests/helper/redis.py:
class MockRedis:
# Implementation
root/tests/stuff/test.py:
from helper.redis import MockRedis
def test():
print(MockRedis().get('stuff'))
This approach keeps your conftest.py clean and focused on fixtures, plugins, and hooks.