pytest-dev / pytest

The pytest framework makes it easy to write small tests, yet scales to support complex functional testing
https://pytest.org
MIT License
12.1k stars 2.68k forks source link

parser.addoption has a buggy argument parser (relative path-like strings) #6904

Open themanifold opened 4 years ago

themanifold commented 4 years ago

If I provide an existing relative path to pytest via parser.addoption then I get the following error message:

ERROR: usage: pytest [options] [file_or_dir] [file_or_dir] [...]
pytest: error: unrecognized arguments: --var-file
  inifile: None
  rootdir: /home/user/workspace

This does not happen to a relative path that is non-existent.

If you add an equal sign (=) instead of a blank space, this error does not occur.

This is slightly confusing to me as I do not see why parser.addoption cares about whether we're passing in a file (I would have thought it was just deal with the string). And if it does care about whether something is a file, why is it OK with a nonexistent file?

A minimal bit of code that will reproduce this, conftest.py

def pytest_addoption(parser):
    parser.addoption(
        "--var-file",
        action="store",
    )

Place this in a folder with an existing relative file above it, e.g.:

foo.txt
test/conftest.py
test/bar.txt

Enter the test folder and execute pytest --var-file ../foo.txt and observe the error message above.

Running pytest --var-file bar.txt will not produce an error message Running pytest --var-file ../notthere.txt will not produce the error message Running pytest --var-file=../foo.txt will not produce the error message

Output of pip freeze:

pip freeze
atomicwrites==1.3.0
attrs==19.3.0
importlib-metadata==1.5.0
more-itertools==8.2.0
packaging==20.3
pluggy==0.13.1
py==1.8.1
pyparsing==2.4.6
pytest==5.3.5
six==1.14.0
wcwidth==0.1.8
zipp==3.1.0
lsb_release -a
LSB Version:    n/a
Distributor ID: ManjaroLinux
Description:    Manjaro Linux
Release:    18.1.5
Codename:   Juhraya
python --version
Python 3.8.1

Note, observed this in pytest 5.0.1 as well.

RonnyPfannschmidt commented 4 years ago

at first glance this looks like this is not a initial conftest, i think pytest needs to warn more about plugin registration with the addoption hook when its already too late for that

if you move it one folder up it should work

themanifold commented 4 years ago

@RonnyPfannschmidt Sorry, I'm not super experienced with pytest (or confest). I'm not sure what you mean by your message.

I don't understand why pytest is trying to register a plugin when I use the addoption hook to create a unrelated flag.

When you say move "it" up one folder, do you mean confest? I can't really do that in my example because the file I'm referring to is not part of the test project - conftest belongs in the test folder IMO.

RonnyPfannschmidt commented 4 years ago

i mean moving the conftest up one folder, pytest no longer scans all of the conftests in all of the folders because people did horrid stuff, sorry about that one

themanifold commented 4 years ago

OK, I understand your work around, but why does putting an equal sign there make it work?

RonnyPfannschmidt commented 4 years ago

@themanifold with the =, pytest doesnt consider it as a existing path contributiong to finding the rootdir

this is a issue with finding the correct rootdir as only conftests in it are considered as initial conftests

if you cringe from the explanation thats natural, i also cringed when writing it (the horrors of bugfix collusion)

adrian-arg commented 3 years ago

I'm getting the same behavior I'm building a little framework for a demo and I have the webdrivers in a folder called webdrivers.

If I use something like --driver_path webdrivers/chromedriver, it breaks with the error:

"ERROR: usage: _jb_pytest_runner.py [options] [file_or_dir] [file_or_dir] [...] _jb_pytest_runner.py: error: unrecognized arguments: --driver_path inifile: /home/adrian/Projects/myframework/pytest.ini rootdir: /home/adrian/Projects/myframework"

Using it like this makes it work as stated above --driver_path=webdrivers/chromedriver

Using anything that doesn't match a folder works as well --driver_path linux/chromedriver