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
11.82k stars 2.63k forks source link

Allow plugins to cause a "command line usage error" #11940

Open devds96 opened 6 months ago

devds96 commented 6 months ago

What's the problem this feature will solve?

I am trying to write a pytest plugin that has several command line flags. Some combinations of these flags are "illegal", for example in the sense that they contradict each other. However, I noticed that there seems to be no way to terminate the program with the standard "usage error" output as for example seen from argparse.

Describe the solution you'd like

There should be a method, for example named cmdline_error, for example at the Config class, that causes the usage error message "ERROR: usage: pytest [options] ..." to appear, followed by the termination of the program with the appropriate exit code.

Alternative Solutions

Currently, the way I achieve this is by accessing the error function of the underlying argparse parser via config._parser._getparser().error in the pytest_configure hook. But of course, accessing names starting with underscores is not generally a good idea.

nicoddemus commented 6 months ago

Hi,

I would use raise pytest.UsageError explaining the motive (for example --foo and --bar cannot be passed at the same time). It won't automatically print the usage: string, but perhaps this is a good enough-solution?

devds96 commented 6 months ago

I guess that could be a viable workaround, although it is not exactly the same. It might at least be better than hacking access to _getparser().

RonnyPfannschmidt commented 6 months ago

I strongly recommend not getting the parser for now

I hope i can eventually remove argparse, but work on that stalled for personal reasons

nicoddemus commented 6 months ago

@devds96 do you think using pytest.UsageError is good enough, or strongly feel we should add a new exception type for this?

The-Compiler commented 6 months ago

Maybe we could have a raise pytest.UsageError(..., show_usage=True) or somesuch that causes pytest to add parser.show_usage() to the message? We already do something similar here:

https://github.com/pytest-dev/pytest/blob/9454fc38d3636b79ee657d6cacf7477eb8acee52/src/_pytest/config/argparsing.py#L416-L424

devds96 commented 6 months ago

I think the show_usage flag would be a good solution. The way it works currently, I do not think that a separate exception type would be necessary.

nicoddemus commented 6 months ago

Good idea. :+1:

nicoddemus commented 6 months ago

To summarize, the current proposal is to add show_usage:bool=False to UsageError:

raise pytest.UsageError(..., show_usage=True)