47

Where and how does py.test look for fixtures? I have the same code in 2 files in the same folder. When I delete conftest.py, cmdopt cannot be found running test_conf.py (also in same folder. Why is sonoftest.py not searched?

# content of test_sample.py
def test_answer(cmdopt):
    if cmdopt == "type1":
        print ("first")
    elif cmdopt == "type2":
        print ("second")
    assert 0 # to see what was printed

content of conftest.py

import pytest

def pytest_addoption(parser):
    parser.addoption("--cmdopt", action="store", default="type1",
        help="my option: type1 or type2")

@pytest.fixture
def cmdopt(request):
    return request.config.getoption("--cmdopt")

content of sonoftest.py

import pytest

def pytest_addoption(parser):
    parser.addoption("--cmdopt", action="store", default="type1",
        help="my option: type1 or type2")

@pytest.fixture
def cmdopt(request):
    return request.config.getoption("--cmdopt")

The docs say

http://pytest.org/latest/fixture.html#fixture-function

  1. pytest finds the test_ehlo because of the test_ prefix. The test function needs a function argument named smtp. A matching fixture function is discovered by looking for a fixture-marked function named smtp.
  2. smtp() is called to create an instance.
  3. test_ehlo() is called and fails in the last line of the test function.
codeape
  • 97,830
  • 24
  • 159
  • 188
Dave
  • 4,184
  • 8
  • 40
  • 46

3 Answers3

39

py.test will import conftest.py and all Python files that match the python_files pattern, by default test_*.py. If you have a test fixture, you need to include or import it from conftest.py or from the test files that depend on it:

from sonoftest import pytest_addoption, cmdopt
ecatmur
  • 152,476
  • 27
  • 293
  • 366
  • 2
    By some reason, if you are using Pycharm it detects the import of the fixture as unused (At least in version 2021.2.3). Anyway if you remove the fixture import it stops working. – Drubio Nov 23 '21 at 12:02
27

Here is the order and where py.test looks for fixtures (and tests) (taken from here):

py.test loads plugin modules at tool startup in the following way:

  1. by loading all builtin plugins

  2. by loading all plugins registered through setuptools entry points.

  3. by pre-scanning the command line for the -p name option and loading the specified plugin before actual command line parsing.

  4. by loading all conftest.py files as inferred by the command line invocation (test files and all of its parent directories). Note that conftest.py files from sub directories are by default not loaded at tool startup.

  5. by recursively loading all plugins specified by the pytest_plugins variable in conftest.py files

Jackson Tale
  • 25,428
  • 34
  • 149
  • 271
Alex Okrushko
  • 7,212
  • 6
  • 44
  • 63
6

I had the same issue and spent a lot of time to find out a simple solution, this example is for others that have a similar situation as I had.

  • conftest.py:
import pytest

pytest_plugins = [
 "some_package.sonoftest"
]

def pytest_addoption(parser):
  parser.addoption("--cmdopt", action="store", default="type1",
      help="my option: type1 or type2")

@pytest.fixture
def cmdopt(request):
  return request.config.getoption("--cmdopt")
  • some_package/sonoftest.py:
import pytest

@pytest.fixture
def sono_cmdopt(request):
  return request.config.getoption("--cmdopt")
  • some_package/test_sample.py
def test_answer1(cmdopt):
  if cmdopt == "type1":
      print ("first")
  elif cmdopt == "type2":
      print ("second")
  assert 0 # to see what was printed

def test_answer2(sono_cmdopt):
  if sono_cmdopt == "type1":
      print ("first")
  elif sono_cmdopt == "type2":
      print ("second")
  assert 0 # to see what was printed

You can find a similar example here: https://github.com/pytest-dev/pytest/issues/3039#issuecomment-464489204 and other here https://stackoverflow.com/a/54736376/6655459

Description from official pytest documentation: https://docs.pytest.org/en/latest/reference.html?highlight=pytest_plugins#pytest-plugins

As a note that the respective directories referred to in some_package.test_sample" need to have __init__.py files for the plugins to be loaded by pytest

rafalkasa
  • 1,743
  • 20
  • 20