--ignore option is not relative to rootdir?
It appears that the --ignore option is not specified relative to --rootdir, which is a bit of a problem when you want to execute your tests from a directory other than the project root (particularly if you also want to allow people to execute from the root directory).
Here's a bash script to create an MWE:
cd $(mktemp -d) # New project in a temporary dir
mkdir tests
mkdir otherdir
cat > tests/test_ignored.py <<< EOF
def test_bad():
assert False
raise Exception("I told you to ignore me!")
EOF
cd otherdir
You can then trigger the issue with pytest --rootdir=.. .. --ignore=tests/test_ignored.py. You can see that the file is properly ignored if instead you work in the root directory and do pytest . --ignore=tests/test_ignored.py.
Obviously in this example I can just specify my paths relative to my root directory, but I'm converting over a project to run the tox job in a temporary directory and it's got a bunch of --ignore rules defined in its tox.ini. If I specify relative to the temporary directory, then bare pytest invocations would break. I thought I'd be clever and do something like this:
[testenv]
deps=pytest
setenv = TESTROOT={toxinidir}
changedir = {envtmpdir}
commands = python -m pytest {posargs} --rootdir={toxinidir} {toxinidir}
[pytest]
addopts=
--ignore=${TESTROOT}/tests/test_ignored.py
But alas either that TESTROOT gets expanded too early or not at all (not sure which).
Should the default test root be switched to rootdir? If not, is there any suggested workaround for this? Any special value that expands to rootdir?
Hi @pganssle and sorry for the delay,
This unfortunately is a common misunderstanding about rootdir, from the docs:
Here’s a summary what pytest uses rootdir for:
- Construct nodeids during collection; each test is assigned a unique nodeid which is rooted at the rootdir and takes in account full path, class name, function name and parametrization (if any).
- Is used by plugins as a stable location to store project/test run specific information; for example, the internal cache plugin creates a .pytest_cache subdirectory in rootdir to store its cross-test run state.
Having said that, --ignore is not based on rootdir, but always based on the current working directory.
Here's the snippet responsible:
https://github.com/pytest-dev/pytest/blob/cff7843f3b56e170fe0c81117a6f62da17cf6e0c/src/_pytest/main.py#L295-L303
Back to rootdir, I believe the name is a bit unfortunate because it gives the impression it will be the "collection root", which is not true. This confuses people sometimes, specially when they use --rootdir and expect collection/configuration files to start from there.
I'm not sure what to do about it, unfortunately...
Things can get even worse when you use --ignore along with --deselect. The latter points to nodeids and, as explained by @nicoddemus, does honor rootdir, so you end up having to worry about working directory for the --ignore option and rootdir for --deselect.
And since pytest will keep silent even if it can't find what to ignore/deselect, you can spend quite some time trying to figure out what's going on.