-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
pytest.Config.getoption default
argument not working as expected
#10558
Comments
Definitely a bug, and surprising one at that. Not sure we need to consider it a breaking change, given that the current behavior is definitely wrong according to the docs, but I would probably only release a fix in the next minor version to avoid any disruption. |
Hi, has this been fixed already? May I fix this? |
Nobody has worked on it @sus-pe, you are welcome to give it a shot! 👍 |
Cool I'm doing it :) |
Specification of IssueThe definition of "option existence"Before talking about the issue it is important to well define the term of an option existing vs not existing, as the docs distinguish between the two when defining its expected behaviour. As we have observed, an option "exists" if the parser has been taught to expect it using Docs vs Observed BehaviourBelow, we present our observation of If we have observed a mismatch between the expected behaviour as documented (to the best of our ability) and how the code actually behaves, we have added such mention (in bold at the relevant cell) by mentioning "doc:" to signal that this is how we understand the documented behaviour, and "code:" to signal that this is the behaviour observed by running the method.
option doesn't exist
option exists and is None (value not provided in command line)
option exists and is not None (value provided by in command line)
Oddity of the
|
Thanks @sus-pe for the detailed summary! TBH I'm not sure that this very confusing API is salvageable. This function has been existed since forever, so it probably has grown organically. My thoughts:
Perhaps we would do better to deprecate def get(self, name: str) -> Any:
""""
Gets the option named ``name`` (you can also use the user facing variant ``--name``), or raises
`OptionNotDefinedError`.
"""" With that the API is very straightforward for the user to use, and they can catch the Let's see what others think. |
I like your suggestion, raising an indicative exception is great to fail the test and ultimately the CI to catch the bug, unlike the skip which would not. |
Pinging @The-Compiler @bluetech @RonnyPfannschmidt @asottile to see what they think. |
i'd love to replace the combination of options/arguments/ini alltogether, but i havent gotten around actually writing a testable version of the new idea, so we can go for such a api first |
I like this 👍 |
One thing I realized later, which might be weird/confusing (or not): Assuming with go with
I think 2) is fine as is legacy/deprecated, but does the similarity between 1) and 3) bother anyone? I think it is fine (3 is better as it conveys |
I see your point @nicoddemus, it is confusing that we'd have two different exceptions to indicate the same problem, would it be better to choose just a single approach? Either choose option (1) or (3) and let everything else be consistent with the chosen approach. Something that I notice is that both (1) and (3) are dynamic bindings, as class MySpecialOptions(PytestOption):
FOOBAR = ...
KISHKEBAB = ...
def test_foobar(config):
config.get(MySpecialOptions.FOOBAR) The def get(self, name: PytestOption) -> Any:
... |
@sus-pe I would not change attribute access ( Taking advantage of introducing a new API to also introduce a more type-checked API is an interesting idea, however:
Throwing some quick ideas around to see where we can at. Using many options like you suggest will give some type-safety, however still returning Here is how we define an option and use it: def pytest_addoption(parser):
parser.addoption(
"--runslow", action="store_true", default=False, help="run slow tests"
)
def pytest_collection_modifyitems(config, items):
if config.getoption("--runslow"):
# --runslow given in cli: do not skip slow tests
return We could make options a first-class citizen, which would could then be used to both declare them and use them: RunSlow = pytest.Option[bool](
"--runslow",
action=pytest.OptionAction.StoreTrue,
default=False,
help="run slow tests",
)
def pytest_register_options(config): # new hook
config.register_option(RunSlow)
def pytest_collection_modifyitems(config, items):
if config.get(RunSlow):
# --runslow given in cli: do not skip slow tests
return
As I said just throwing some quick ideas, but going this route is is opening a whole can of worms and might require some good discussion before we can agree on an API. But I personally would like to make it clear that even if we decide on a new API, I would not deprecate the old APIs1, at least not for a few years. Footnotes
|
That is reasonable @nicoddemus, as for the original issue, we could for now remedy it with the agreed upon solutions you have suggested. How would you like us to proceed? Should we still fix the existing We are still up for the task if you see a way to bring this issue to a resolution, and the discussion for a modern typeful API for pytest options could get done independently. |
Regarding About the "new API", at first we should see if others see it is a good idea, and if so, open a new issue/proposal. |
Hi everyone, what's the status of this? The documentation appears unchanged and the bug is still there (at least on 8.3.3). |
@ugomancz no change I guess, my suggestion:
Still stands I think. |
My apologies, I want to fix the docs as discussed last year, will attempt to open PR soon |
feedback on clarity of proposed docstring is welcomed here: |
For full context see issue pytest-dev#10558
For full context see issue pytest-dev#10558
I wonder if we should rename |
I like the "declared" semantics over the "exists" semantics |
For full context see issue pytest-dev#10558
For full context see issue pytest-dev#10558
For full context see issue pytest-dev#10558
For full context see issue pytest-dev#10558
Closes #10558. --------- Co-authored-by: suspe <[email protected]> (cherry picked from commit d8d607e)
pip list
from the virtual environment you are usingI'm running into an issue where the
default
argument topytest.Config.getoption
is not working as expected, or at least not as it is documented.Reproduction steps
pytest_generate_tests
hook in aconftest.py
file.metafunc
argument to access thepytest.Config
object viametafunc.config
.getoption
on an option that was not passed while specifying a default, E.G.metafunc.config.getoption(name="foobaz", default={})
Exepected behavior
The empty dictionary is returned as it is set as the default.
Actual behavior
None
is returned instead.Possible fix
The issue appears to be the check inside
getoption
on line 1541:Since
skip
is not passed, it defaults toFalse
which means even if adefault
is set to something other thannotset
, that default value will never be returned unlessskip
is also set toTrue
. I believe the fix is to change line 1541 to:if val is None:
This will be a breaking change, however, as it would mean not passing
default
would lead to aValueError
being raised whenskip
isFalse
.Minimal reproduction example
Pip list
Actually it's `poetry show`
pytest and OS versions
The text was updated successfully, but these errors were encountered: