-
Notifications
You must be signed in to change notification settings - Fork 22
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
"check" convenience shortcut for subtests fixture #28
Conversation
- Support nested `subtests.test()` contexts similar to `unittest.TestCase.subTest()` chaining of argument sets. - Make `subtests` instance a re-entrable context manager similar to `subtests.test()`. - Make `subtests` instance a callable that sets context (scope) for further subtests or for nested scopes only if return value is used as a context manager. - Add `check` concise alias for the `subtests` fixture. Essentially, the goal is to adapt `pytest-subtests` for checking of multiple aspects of compound objects, e.g. a class fields, withing a single unit test and to get report with all failures at once instead of the first error only. from datetime import datetime def test_fields(check): dt = datetime.utcfromtimestamp(1234567890) with check: assert dt.year == 2009, "Year is OK" with check: assert dt.month == 1 with check: assert dt.day == 13, "Day is OK" with check: assert dt.hour == 27 Use with `--tb=short` option. The bright idea of context manager shortcut belongs to @ionelmc: okken/pytest-check#9
Let's add some sugar to make writing tests more convenient. The bright idea is borrowed from okken/pytest-check#9 (@ionelmc), adapted for New fixture from datetime import datetime
def test_fields(check):
dt = datetime.utcfromtimestamp(1234567890)
with check: assert dt.year == 2009, "OK"
with check: assert dt.month == 1
with check: assert dt.day == 13, "OK"
with check: assert dt.hour == 27 Output with
The fixtures are callable, so the purpose of checks could be set for a nested scope or for following usages. from datetime import datetime
def test_details_example(check):
ts = 1234567890
dt = datetime.utcfromtimestamp(ts)
with check(timestamp=ts):
check("date")
with check: assert dt.year == 2009, "OK"
with check: assert dt.month == 1
with check: assert dt.day == 13, "OK"
check("time")
with check("hour"): assert dt.hour == 27
with check: assert dt.minute == 13
When subtest failure leads to test failure (see #27), summary report becomes less confusing. |
Please, consider, this pull request as a proposal to be discussed. I suppose that brief form of context manager feature of I was looking for a python way to allow non-fatal (soft) assertion similar to Currently I am not happy with pytest report summary, but it is loosely related to the changes. Final list of failures is not informative enough to identify particular failed check. Assert message is not the best one. I have tried to include subtest description to test The goal is failure reports that shed as much as possible light on the problem with code without following debugging and even without excessive scrolling of the report. So I would like to here ideas of further improvements. |
I believe that only the message should be customizable in the output (eg: be able to replace the " If you want to take kwargs go for that, eg:
or
Using those kwargs for markers (behavior changing) is way more useful than more output cunstomization (that you can do with the msg anyway). |
Keyword arguments are mostly shortcut for As to
The greater problem with subtest expected failures and skips is accounting in the parent test. In my opinion subtest result is less important than test result. Though the former affects the latter, the counters should be different. As a possible alternative if "xfail" mark is desired for subtests
could be considered. |
Well I guess I don't see myself using nesting. As a matter of fact I'm wondering what are the actual usecases for nesting/scoping. I guess a fixture using the check cm to do some asserts before returning whatever, but would that actually work? Should be part of the test suite I think. |
Thanks @maxnikulin but I think this is out of scope for this plugin: my intent is to have the same characteristics of FWIW I use from datetime import datetime
def test_fields(data_regression):
dt = datetime.utcfromtimestamp(1234567890)
data = dict(
year=2009,
month=1,
day=13,
hour=27,
)
data_regression.check(data) |
@ionelmc, sorry, I do not have real life examples of scopes. As to nesting I was trying to mimic |
pytest-regression is useful but it addresses a bit different problem. My example is not the best one. Description of pytest-regression correctly addresses the issue that all inconsistencies should be reported, not the first one. Sometimes I prefer to have data in the test code to grasp everything at a glance without browsing through files scattered over various directories Sometimes I feel more confident when some invariants are checked through function calls in addition to plain data fields. Certainly reference data must obey the invariants |
I would not mind if
however plain In my opinion support of Notice that I believe the weak point is error reporting, both stack trace and progress/summary. I have not realized where I would like to see extension points in pytest core. Currently I would prefer short stack trace for subtests by default. Maybe it is worth allowing a test to have multiple exceptions to postpone output to the make report hook. It would be nice to see msg+kwargs in progress and summary reports to quickly identify failed parts. Actually Feel free to just close this pull request or to adapt part related to nested scopes if you wish. |
Indeed that's the original plan: to put the functionality into a plugin and eventually merge it into the core. Things have been moving very slowly on that front though, I admit. But for this reason I don't think we should deviate from what's available in So for now I don't think we should add this convenience to it, but I deeply appreciate the interest and your work in putting out this PR! |
subtests.test()
contexts similar tounittest.TestCase.subTest()
chaining of argument sets.subtests
instance a re-entrable context managersimilar to
subtests.test()
.subtests
instance a callable that sets context (scope)for further subtests or for nested scopes only if return
value is used as a context manager.
check
concise alias for thesubtests
fixture.Essentially, the goal is to adapt
pytest-subtests
for checkingof multiple aspects of compound objects, e.g. a class fields, withing a
single unit test and to get report with all failures at once instead of
the first error only.
Use with
--tb=short
option.