'Way to add pytest options outside top level conftest?

I have a project that defines testing support modules, including py.test plugins in a package subdirectory like this:

bokeh/_testing
├── __init__.py
├── plugins
│   ├── __init__.py
│   ├── bokeh_server.py
│   ├── examples_report.jinja
│   ├── examples_report.py
│   ├── file_server.py
│   ├── implicit_mark.py
│   ├── integration_tests.py
│   ├── jupyter_notebook.py
│   ├── log_file.py
│   └── pandas.py
└── util
    ├── __init__.py
    ├── api.py
    ├── examples.py
    ├── filesystem.py
    ├── git.py
    └── travis.py

Several of the plugins need to define new options with parser.addoption. I would like these calls to be made inside the respective plugin modules. However, if I do that, and include those plugins in a test file with, e.g.

# test_examples.py
pytest_plugins = (
    "bokeh.testing.plugins.bokeh_server",
    "bokeh.testing.plugins.examples_report",
)

# pytest.mark.examples test code here 

Then pytest complains that any custom command line options are undefined:

(base) ❯ py.test -s -v -m examples --diff-ref FETCH_HEAD --report-path=examples.html
usage: py.test [options] [file_or_dir] [file_or_dir] [...]
py.test: error: unrecognized arguments: --diff-ref --report-path=examples.html
  inifile: /Users/bryanv/work/bokeh/setup.cfg
  rootdir: /Users/bryanv/work/bokeh

The only way I have found around this, is to collect ALL custom options in a single pytest_addoption in the top-level conftest.py:

# conftest.py
pytest_plugins = (
    "bokeh.testing.plugins.implicit_mark",
    "bokeh.testing.plugins.pandas",
)

# Unfortunately these seem to all need to be centrally defined at the top level
def pytest_addoption(parser):
    parser.addoption(
        "--upload", dest="upload", action="store_true", default=False, help="..."
    )

    # ... ALL other addoptions calls for all plugins here ...

As I said, this works, but is very inflexible in terms of code organization. It would be preferable to have a way for the options for the examples.py plugin to in the examples.py module, with the code it relates to.

Another possibility would presumably be to bring in all the plugins in the top-level conftest.py, but some of the plugins are very heavyweight, e.g. depend on Selenium, and I would not like to require that all that be installed just to run basic tests.

Is there another way to accomplish this, and if so, how?



Solution 1:[1]

As noted above, as of Pytest 3.6.2, options must be added "only in plugins or conftest.py files situated at the tests root directory due to how pytest discovers plugins during startup."

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 bigreddot