pytest-dev / pytest-dev/pytest

pytest needs a supported way to specify paths relative to pytest root directory

Open
#9,619 1 comment 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

topic: config type: proposal
Dominant language
Python
Stars
14.5k
Forks
3.4k
Avg merge
2d 9h
Merged PRs (30d)
35

Description

What's the problem this feature will solve?

There are cases where it would be very useful to be able to specify paths in pytest options that are relative to the test root (or some similar fixed point. Without this, there is no way to read or write things to/from locations that are in a fixed location relative to the repository root.

Good examples are the pytest-cov and pytest-html plugins, where you need to specify an output directory/file. If one wants that output to always end up in the same place (regardless of the subdirectory where pytest is run), there's no way to specify that path short of using an absolute path, which would mean each developer would need to update the pytest config locally for their particular development environment, which is not at all ideal.

Even if one makes the assertion that pytest output should always be relative to the directory in which it is being executed (I don't think that's a valid assertion, but I could see it being made), there are places this is still a problem -- a good example is the pytest-html plugin, where you can optionally specify a CSS file to go along with the generated HTML report. In --self-contained-html mode, where the plugin reads the specified CSS file and includes it inline in the final html file. Even if you want the output report.html to be written relative to the current directory, there's no way to specify the location of the CSS file in a way that it can always be accessed, regardless of current directory.

I imagine this problem exists across numerous plugins (almost anything that accepts command line options for specifying a file or directory for reading or writing), so a general solution to this seems useful.

Describe the solution you'd like

I don't have specific solutions in mind, other than that it seems like there would need to be some way to specify paths with some kind of placeholder for the pytest root directory or similar. See below for my current solution.

One possible solution would be to simply not remove the pytest_cmdline_preparse hook support, as that appears to be the only current way to accomplish this.

Alternative Solutions

My current solution, which works for the moment, is to use a top level conftest.py with contents of:

def pytest_cmdline_preparse(config, args):
    for i, arg in enumerate(args):
        if "@rootdir@" in arg:
            newpath = arg.replace("@rootdir@", str(config.rootdir))
            args[i] = os.path.normpath(newpath)

And then I can specify arguments in my pyproject.toml (or pytest.ini or whatever) in the form of --css=@rootdir@/tests/report.css, and the preparse hook substitutes the correct rootdir before the arguments get passed to the plugin command line parsers. This isn't a good long-term solution, though, because with 7.0 using that hook generates a warning, and it will presumably be removed in pytest 7.1.

I've considered using tox, which allows a similar form of command-line substitution when calling pytest, but this makes it difficult to do quick tests from random test subdirectories and otherwise ends up being a far more heavyweight solution than is desirable.

I've tried using some of the other available hooks to substitute the path for command line options that need it, but none seems to execute early enough to stop things from breaking. I've tried other suggestions (alas, I don't have a list, it was some time ago) offered by people on the #pytest-help channel on the support discord, without finding other functional solutions.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the issue's top-level conftest.py workaround and the pytest_cmdline_preparse hook, then review how paths from pyproject.toml or pytest.ini reach plugin command-line parsers. Compare the behavior from repository-root and nested test-directory invocations; done means pytest offers a supported way for plugins to resolve configured paths relative to its root directory.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
testing
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.