-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Document parametrizing conditional raises #4682
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
Document parametrizing conditional raises #4682
Conversation
Addressing issues pytest-dev#4324 and pytest-dev#1830
Codecov Report
@@ Coverage Diff @@
## master #4682 +/- ##
=========================================
+ Coverage 95.69% 95.7% +<.01%
=========================================
Files 113 113
Lines 24902 24910 +8
Branches 2459 2459
=========================================
+ Hits 23830 23840 +10
+ Misses 757 755 -2
Partials 315 315
Continue to review full report at Codecov.
|
Codecov Report
@@ Coverage Diff @@
## master #4682 +/- ##
==========================================
- Coverage 95.69% 95.68% -0.02%
==========================================
Files 113 113
Lines 24902 24970 +68
Branches 2459 2479 +20
==========================================
+ Hits 23830 23892 +62
- Misses 757 762 +5
- Partials 315 316 +1
Continue to review full report at Codecov.
|
I think the recipe in #1830 (comment) is more complete. The python2 block can be implemented in the same way as this (if needed) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a ton @arel!
@asottile I don't quite follow. The recipe you linked to is more verbose and requires backporting if sys.version_info >= (3, 7):
from contextlib import nullcontext
elif sys.version_info >= (3, 3):
from contextlib import ExitStack as nullcontext
else:
from contextlib2 import ExitStack as nullcontext whereas, the recipe below uses only built-in features and supports Python 2.5 and above: from contextlib import contextmanager
@contextmanager
def does_not_raise():
yield |
@arel pytest doesn't support 2.6 and the recipe improves ootb support for other versions |
I don't even think you need the recipe, but the important information is basically (something like this): If you need to parametrize based on "raising" you can implement a ``does_not_raise`` contextmanager using a noop contextmanager.
If you're only supporting python3.7+ you can use:
.. code-block:: python
from contextlib import nullcontext as does_not_raise
If you're only supporting python3.3+ you can use:
.. code-block:: python
from contextlib import ExitStack as does_not_raise
If you need to support older versions you can either use the `contextlib2` backport:
.. code-block:: python
from contextlib2 import ExitStack as does_not_raise
or you can define your own noop contextmanager
.. code-block:: python
from contextlib import contextmanager
@contextmanager
def does_not_raise():
yield I might even go so far as to put some opinions in there as well. Something like "You might be over-engineering your tests with parametrize a bit -- it will likely read better if you split your testcases into successful cases and failure cases instead of trying to bake conditional logic into |
@asottile perhaps you should mark this PR as "request changes" so it is clear in the Pull Requests view that this PR still has required work? Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(see above)
I feel strongly that the example as-is is clearer than the alternative, and I fail to see a benefit in complicating it. I don't believe there is a correctness benefit, performance benefit, or pedagogical benefit in using Maybe I wasn't clear, but the The main point someone needs to get from the documentation is: in order to parametrize |
Correct, but it's better to use the builtin things where you have to write zero code. pytest doesn't care about python 2.5 / 2.6 / 3.0 / 3.1 / 3.2 / 3.3 support and soon won't care about python2.x support and so documenting a pattern in a way that's soon to become obsolete should be the last goal. Put the newest things first, and the "ok well if you absolutely must support old stuff use this" last please :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great! I don't have write access, so I'll leave merging up to one of you. Thanks! |
Oops I forgot |
Thanks for your contribution! I just wondered if / why this wasn't done for the features branch? |
it's entirely docs / tests -- it'll make it into |
Oh, missed that afe9fd5 was "reverted"/removed again (when looking at new commits on master). |
This PR addresses issues #4324
and #1830, which documents how to usepytest.raises
conditionally together withpytest.mark.parametrize
.I added documentation on how to use a null context manager to complement
pytest.raises
as well as added tests for the documented code.Based on the discussion in #4679, I removed
does_not_raise
from the core library, and instead will rely on users copying and pasting the boilerplate.I used:
instead of
because it works from Python 2.5 and up without installing additional libraries or backporting, whereas
nullcontext
is only introduced in Python 3.7.Closes #4324
Thanks for submitting a PR, your contribution is really appreciated!
Here's a quick checklist that should be present in PRs (you can delete this text from the final description, this is
just a guideline):
changelog
folder, with a name like<ISSUE NUMBER>.<TYPE>.rst
. See changelog/README.rst for details.master
branch for bug fixes, documentation updates and trivial changes.features
branch for new features and removals/deprecations.Unless your change is trivial or a small documentation fix (e.g., a typo or reword of a small section) please:
AUTHORS
in alphabetical order;