Question: Summary: I'm trying to set up a custom pytest option with the pytest_addoption feature. But when trying to configure my project with a project.toml file while using the said custom option, I'm getting the following error: $ pytest --foo foo ERROR: usage: pytest [options] [file_or_dir] [file_or_dir] [...] pytest: error: unrecognized arguments: --foo inifile: /home/vmonteco/Code/MREs/pytest__addoption__pyproject_toml/01_adding_pyproject.toml/pyproject.toml rootdir: /home/vmonteco/Code/MREs/pytest__addoption__pyproject_toml/01_adding_pyproject.toml  Why is this problem occurring despite the configured test path and how could I solve it? Used versions are:  Python 3.10.13 Pytest 8.1.1   How to reproduce: Step 1 - before organizing the project, it works: I start with a very simple test in a single directory. $ tree . ├── conftest.py └── test_foo.py 1 directory, 2 files $   conftest.py:  import pytest def pytest_addoption(parser): parser.addoption("--foo", action="store") @pytest.fixture def my_val(request): return request.config.getoption("--foo")   test_foo.py:  def test_foo(my_val): assert my_val == "foo"  $ pytest --foo bar =============================== test session starts =============================== platform linux -- Python 3.10.13, pytest-8.1.1, pluggy-1.5.0 rootdir: /home/vmonteco/code/MREs/pytest__addoption__pyproject_toml/00_simplest_case collected 1 item test_foo.py F [100%] ==================================== FAILURES ===================================== ____________________________________ test_foo _____________________________________ my_val = 'bar' def test_foo(my_val): > assert my_val == "foo" E AssertionError: assert 'bar' == 'foo' E E - foo E + bar test_foo.py:2: AssertionError ============================= short test summary info ============================= FAILED test_foo.py::test_foo - AssertionError: assert 'bar' == 'foo' ================================ 1 failed in 0.01s ================================ $  Step 2 - When adding an empty pyproject.toml and reorganizing the project, it fails: $ tree . ├── my_project │ └── my_tests │ ├── conftest.py │ ├── __init__.py │ └── test_foo.py └── pyproject.toml 3 directories, 4 files $ pytest --foo bar ERROR: usage: pytest [options] [file_or_dir] [file_or_dir] [...] pytest: error: unrecognized arguments: --foo inifile: /home/vmonteco/code/MREs/pytest__addoption__pyproject_toml/01_adding_pyproject_toml/pyproject.toml rootdir: /home/vmonteco/code/MREs/pytest__addoption__pyproject_toml/01_adding_pyproject_toml $  Notes:  In doubt, I also added an __init__.py file. The pyproject.toml seems to be recognized despite not having the required [tool.pytest.ini_options] table, thus apparently contradicting the documentation.  However, there's a simple workaround that seems to work in this specific case: Just manually passing the test path to my tests as command line argument seems enough to make things work correctly again: $ pytest --foo bar my_project/my_tests =============================== test session starts =============================== platform linux -- Python 3.10.13, pytest-8.1.1, pluggy-1.5.0 rootdir: /home/vmonteco/code/MREs/pytest__addoption__pyproject_toml/01_adding_pyproject_toml configfile: pyproject.toml collected 1 item my_project/my_tests/test_foo.py F [100%] ==================================== FAILURES ===================================== ____________________________________ test_foo _____________________________________ my_val = 'bar' def test_foo(my_val): > assert my_val == "foo" E AssertionError: assert 'bar' == 'foo' E E - foo E + bar my_project/my_tests/test_foo.py:2: AssertionError ============================= short test summary info ============================= FAILED my_project/my_tests/test_foo.py::test_foo - AssertionError: assert 'bar' == 'foo' ================================ 1 failed in 0.02s ================================ $  But I'd like to avoid that and I'd rather have my project correctly configured. Step 3 - Unsuccessfully trying to configure testpaths in the pyproject.toml. The best explanation I found so far relies on the following points from the documentation:  The necessity to put pytest_addoption in an "initial" conftest.py:  This hook is only called for initial conftests.  pytest_addoption documentation   What is actually an "initial conftest.py": Initial conftest are for each test path the files whose path match <test_path>/conftest.py or <test_test>/test*/conftest.py.   by loading all “initial “conftest.py files:   determine the test paths: specified on the command line, otherwise in testpaths if defined and running from the rootdir, otherwise the current dir for each test path, load conftest.py and test*/conftest.py relative to the directory part of the test path, if exist. Before a conftest.py file is loaded, load conftest.py files in all of its parent directories. After a conftest.py file is loaded, recursively load all plugins specified in its pytest_plugins variable if present.   Plugin discovery order at tool startup    So, if I understand well:  my error seems to occurs because if I don't provide an explicit test path, the current directory is used. But in that case, my conftest.py is too deep into the arborescence to be used as an initial conftest.  With my workaround, explicitly passing a deeper test path solves this by making the conftest "initial" again.   From this, it would seem appropriate to try to translate my command line argument path into a bit of configuration (testpaths) as shown in the relevant documentation. But when trying to run my command again, I still get the same error: $ cat pyproject.toml [tool.pytest.ini_options] testpaths = [ "my_project/my_tests", ] $ tree . ├── my_project │ └── my_tests │ ├── conftest.py │ ├── __init__.py │ └── test_foo.py └── pyproject.toml 3 directories, 4 files $ pytest --foo bar ERROR: usage: pytest [options] [file_or_dir] [file_or_dir] [...] pytest: error: unrecognized arguments: --foo inifile: /home/vmonteco/code/MREs/pytest__addoption__pyproject_toml/02_attempt_to_solve/pyproject.toml rootdir: /home/vmonteco/code/MREs/pytest__addoption__pyproject_toml/02_attempt_to_solve $  I also tried to use a different kind of configuration file: $ cat pytest.ini [pytest] testpaths = my_project/my_tests $ pytest --foo bar ERROR: usage: pytest [options] [file_or_dir] [file_or_dir] [...] pytest: error: unrecognized arguments: --foo inifile: /home/vmonteco/code/MREs/pytest__addoption__pyproject_toml/03_with_pytest_ini/pytest.ini rootdir: /home/vmonteco/code/MREs/pytest__addoption__pyproject_toml/03_with_pytest_ini $  But it still doesn't solve the problem despite the equivalent as command line argument seems to work. Why?  Addendum - raw output of new step 2 reproduction session: Script started on 2024-08-06 03:23:13+02:00 [TERM="tmux-256color" TTY="/dev/pts/8" COLUMNS="126" LINES="69"] [1m[7m%[27m[1m[0m k..ew_pytest_MRE\]7;file://vmonteco-desktop/home/vmonteco/code/MREs/new_pytest_MRE\ [0m[27m[24m[J[01;32m➜ [36mnew_pytest_MRE[00m [K[?1h=[?2004httree[?1l>[?2004l ktree\[01;34m.[0m ├── [01;34mmy_project[0m │ └── [01;34mmy_tests[0m │ ├── conftest.py │ ├── __init__.py │ └── test_foo.py └── pyproject.toml 3 directories, 4 files [1m[7m%[27m[1m[0m k..ew_pytest_MRE\]7;file://vmonteco-desktop/home/vmonteco/code/MREs/new_pytest_MRE\ [0m[27m[24m[J[01;32m➜ [36mnew_pytest_MRE[00m [K[?1h=[?2004hccat pyproject.toml[1m [0m[0m [?1l>[?2004l kcat\[1m[7m%[27m[1m[0m k..ew_pytest_MRE\]7;file://vmonteco-desktop/home/vmonteco/code/MREs/new_pytest_MRE\ [0m[27m[24m[J[01;32m➜ [36mnew_pytest_MRE[00m [K[?1h=[?2004hccat my_project[1m/[0m[0m/my_tests[1m/[0m[0m/conftest.py[1m [0m[0m [?1l>[?2004l kcat\import pytest def pytest_addoption(parser): parser.addoption("--foo", action="store") @pytest.fixture def my_val(request): return request.config.getoption("--foo") [1m[7m%[27m[1m[0m k..ew_pytest_MRE\]7;file://vmonteco-desktop/home/vmonteco/code/MREs/new_pytest_MRE\ [0m[27m[24m[J[01;32m➜ [36mnew_pytest_MRE[00m [K[?1h=[?2004hcat my_project/my_tests/conftest.py __init__.py[1m [0m[0m [?1l>[?2004l kcat\[1m[7m%[27m[1m[0m k..ew_pytest_MRE\]7;file://vmonteco-desktop/home/vmonteco/code/MREs/new_pytest_MRE\ [0m[27m[24m[J[01;32m➜ [36mnew_pytest_MRE[00m [K[?1h=[?2004hcat my_project/my_tests/__init__.py test_foo.py[1m [0m[0m [?1l>[?2004l kcat\def test_foo(my_val): assert my_val == "foo" [1m[7m%[27m[1m[0m k..ew_pytest_MRE\]7;file://vmonteco-desktop/home/vmonteco/code/MREs/new_pytest_MRE\ [0m[27m[24m[J[01;32m➜ [36mnew_pytest_MRE[00m [K[?1h=[?2004hppython --version[?1l>[?2004l kpython\Python 3.10.13 [1m[7m%[27m[1m[0m k..ew_pytest_MRE\]7;file://vmonteco-desktop/home/vmonteco/code/MREs/new_pytest_MRE\ [0m[27m[24m[J[01;32m➜ [36mnew_pytest_MRE[00m [K[?1h=[?2004hpython --version est --version[?1l>[?2004l kpytest\pytest 8.1.1 [1m[7m%[27m[1m[0m k..ew_pytest_MRE\]7;file://vmonteco-desktop/home/vmonteco/code/MREs/new_pytest_MRE\ [0m[27m[24m[J[01;32m➜ [36mnew_pytest_MRE[00m [K[?1h=[?2004hppytest -fo -foo bar[?1l>[?2004l kpytest\[31mERROR: usage: pytest [options] [file_or_dir] [file_or_dir] [...] pytest: error: unrecognized arguments: --foo inifile: /home/vmonteco/code/MREs/new_pytest_MRE/pyproject.toml rootdir: /home/vmonteco/code/MREs/new_pytest_MRE [0m [1m[7m%[27m[1m[0m k..ew_pytest_MRE\]7;file://vmonteco-desktop/home/vmonteco/code/MREs/new_pytest_MRE\ [0m[27m[24m[J[01;31m➜ [36mnew_pytest_MRE[00m [K[?1h=[?2004h[?2004l Script done on 2024-08-06 03:24:49+02:00 [COMMAND_EXIT_CODE="4"]  link to pastebin

Answer: It looks like it indeed was an usage error (and also facepalm-worthy material): pytest --foo=bar rather than pytest --foo bar. $ pytest --foo bar ERROR: usage: pytest [options] [file_or_dir] [file_or_dir] [...] pytest: error: unrecognized arguments: --foo inifile: /home/vmonteco/code/MREs/pytest__addoption__pyproject_toml/02_attempt_to_solve/pyproject.toml rootdir: /home/vmonteco/code/MREs/pytest__addoption__pyproject_toml/02_attempt_to_solve $ pytest --foo=bar =============================== test session starts =============================== platform linux -- Python 3.10.13, pytest-8.3.2, pluggy-1.5.0 rootdir: /home/vmonteco/code/MREs/pytest__addoption__pyproject_toml/02_attempt_to_solve configfile: pyproject.toml testpaths: my_project/my_tests collected 1 item my_project/my_tests/test_foo.py F [100%] ==================================== FAILURES ===================================== ____________________________________ test_foo _____________________________________ my_val = 'bar' def test_foo(my_val): > assert my_val == "foo" E AssertionError: assert 'bar' == 'foo' E E - foo E + bar my_project/my_tests/test_foo.py:2: AssertionError ============================= short test summary info ============================= FAILED my_project/my_tests/test_foo.py::test_foo - AssertionError: assert 'bar' == 'foo' ================================ 1 failed in 0.02s ================================ $   Addendum: Here's on explanation on why pytest is designed like thas.