How and where does py.test find fixtures

Question:

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.
Asked By: Dave

||

Answers:

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
Answered By: ecatmur

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

Answered By: Alex Okrushko

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

Answered By: rafalkasa
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.